0

I'm trying to create a function, which will multiply each element in a list called s by a parameter x.

First, I experimented around in ghci and found that fn1 s = map (* 2) s works. The I tried to make the function more general by including the factor x as a parameter fn2 x s = map (* x) s. However this leads to an error, when I call the function:

<interactive>:12:1: error:
    • Non type-variable argument in the constraint: Num [a]
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        it :: forall a. (Num a, Num [a]) => [[a]] -> [[a]]

After some additional experimentation I found that I can solve the problem by surrounding the * operator with ()

fn3 x s = map ((*) x) s

What I need help with is why the latter piece of code works while the previous does not.

Any help is appreciated.

3
  • 4
    Did you, by any chance, forget to provide the factor parameter when calling fn2? Can you show how you're calling it exactly? Commented Oct 21, 2020 at 15:29
  • It seems that in the roughly ten times I checked the code I failed to remember the correct order of parameters. Thank you :) Commented Oct 21, 2020 at 15:34
  • 2
    @Bruno The error messages will be much easier to read if you give every top-level function definition an explicit type signature. Commented Oct 21, 2020 at 17:58

1 Answer 1

3

This would happen if you forget to provide the x parameter when calling fn2, for example:

> fn2 [1,2,3]

The compiler sees [1,2,3] where x should be, and it also sees (* x) in the body of the function, and it reckons that [1,2,3] must be a valid argument for operator *. And since operator * is defined in type class Num, the compiler infers that there must be an instance Num [a] - which is exactly what it says in the error message.

The result of such call would be another function, which still "expects" the missing parameter s and once given it, will return a list of the same type as s. Since it's clear from the provided arguments that x :: [a], and you're using map to transform x to the same type, the compiler infers that s :: [[a]], and so the result of calling fn2 like that is [[a]] -> [[a]], which is what the error message says.

Now, the requirement of an instance Num [a] in itself is not a big deal. In fact, if you enable the FlexibleContexts extension (as the error message tells you), this particular error goes away, and you will get another one, complaining that there is no instance Num [a] for any a. And that is the real problem. There is no instance Num [a], because, well, lists are not numbers.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.