views:

171

answers:

2

I'm really at a loss to explain why this is a type error:

foo :: (Eq a) => a -> a
foo _ = 2

Can anyone explain?

+13  A: 

Because the type of

foo "bar"

should be String, according to your signature, but is not (2 is not a String). In your code foo is generic, so it should return an instance of exactly the same type as the argument.

The power of haskell type system gives us additional information - all you can do with the argument inside foo is to check for its equality with something else, but as I can come up with any new type (lets call it Baz) and use foo on it - you can't possibly have any other instances of Baz, so the only way to return an instance of Baz is to return the exact same instance as the argument.

If you rewrote foo like so:

foo _ = True

it would have a signature of foo :: a -> Bool, this is basically what you tried to do, but things get more complicated with numbers.

In general your function has a signature

foo :: (Num t1) => t -> t1

which means that it returns a Num instance for any given argument. (This is because 2 can have many different types in haskell, depending on what you need it can be an Int or a Real or other.)

You should play around with types in ghci, for example:

:t foo

will give you the infered type signature for foo.

:t 2

gives you (Num t) => t which means that 2 can be an instance of any type which implements Num.

Michał Bendowski
+3  A: 

The type signature which you declared means

for all types a (which instantiate Eq), foo takes a value of this type and returns another value of this type

You can even directly write it this way:

foo :: forall a . Eq a => a -> a

Now the function definition

foo _ = 2

says something different:

Regardless of what type is given, return a number.

And of course this types are incompatible.

Example: As Michał stated, since foo "Hello" is given a String, it should return a string, but actually does return a number.

Dario
How does `forall a` make a difference? That looks like the same type to me. Don't all functions essentially have an implicit `forall a` before the type?
Chuck
@Chuck: it makes no difference to the compiler. in this case Dario implies that it may make a difference for the reader
yairchu
Oh, that makes sense now. I'll leave my comment just in case anybody else is slow in the same way as me.
Chuck