1
votes

In the REPL this works:

> mm n = (\n -> n * 2) <$> n
> mm (2:3:Nil)
(4 : 6 : Nil)

in a file this compiles and I can run it:

squareOf ls =
  map (\n -> n * n)  ls

however when I add a type definition to that function

squareOf :: List Int -> Int
squareOf ls =
  map (\n -> n * n)  ls

I get an error:

 Could not match type

    List Int

  with type

    Int


while checking that type t0 t1
  is at least as general as type Int
while checking that expression (map (\n ->
                                       (...) n
                                    )
                               )
                               ls
  has type Int
in value declaration squareOf

where t0 is an unknown type
      t1 is an unknown type

I tried changing the signature to a type alias of the list, and also I tried a forall definition with no luck. If I inspect the definition created when I don't put signatures in my function I get:

forall t2 t3. Functor t2 => Semiring t3 => t2 t3 -> t2 t3

Can anyone explain why my signature is incorrect and also why am I getting this signature for the function?

Cheers

Edit: Thanks for the comments, updating the fn definition so it returns a List Int as well, and , of course it solves the problem

2
Check the return type of your function: Int. But map is structure preserving, so it must return a List of something in your example. - Regis Kuckaertz

2 Answers

3
votes

Assuming you're repl function is the behaviour you're after, you've missed out the map operator (<$>) in your later definitions.

Your repl function (with variables renamed for clarity) has the type:

mm :: forall f. Functor f => f Int -> f Int
mm ns = (\n -> n * 2) <$> ns

Which is to say: mm maps "times two" to something that is mappable" (i.e. a Functor)

Aside: you could be more concise/clear in your definition here:

mm :: forall f. Functor f => f Int -> f Int
mm = map (_*2)

This is similar to your squareOf definition, only now you're squaring so your use of (*) is more general:

squareOf :: forall f. Functor f => Semiring n => f n -> f n
squareOf = map \n -> n * n

Because (*) is a member of the Semiring typeclass.

But the signature you gave it suggests you're after some kind of fold? Let me know what output you expect from your squareOf function and I'll update the answer accordingly.

1
votes

Here is map:

class Functor f where
  map :: forall a b. (a -> b) -> f a -> f b

Narrowing to List Int and Int -> Int, the compiler infers

map :: (Int -> Int) -> List Int -> List Int

So, in squareOf, the expression reduces to a list of integers, not an integer. That is why the compiler complains.