[Haskell-beginners] question on types

James Cook mokus at deepbondi.net
Fri Jul 29 15:23:27 CEST 2011


On Jul 28, 2011, at 7:42 PM, Jake Penton wrote:

> I guess I interpret "f::a" to mean "f is some (any) type a". So why can't it be whatever "1" is, which I suppose is Integer. What is the type system looking for? And why does the constraint (Num a) make things ok?

This right here is the core of your confusion.  As you probably know, in all major typed "object-oriented" languages this is true; for example, in Java "Object foo;" means that "foo" is some type extending Object, and "List bar;" means that "bar" is some type satisfying the List interface.  But in typed functional languages, the mode of "quantification" has the opposite default.  In Haskell, 'f::a' means "FOR EVERY type a, f can be that type".

This is universal quantification - just like the upside-down A ("for all") in logic, the type declaration must be true for all values of "a".  Sometimes it's important to be clear about which type of quantification you're talking about.  When you do, "f :: a" would be written "f :: forall a. a", and what you had in mind would be written "f :: exists a. a".  The key difference is that in the "forall" case, the person using 'f' gets to choose its concrete type, but in the "exists" case the concrete type is chosen by the person defining it.

When type classes are involved, they just add restrictions to the type.  For example, "f :: Num a => a" still has an implied "forall", but the "Num a =>" part means that instead of "for every type a ...", you have "for every type a which implements Num ...".  Similarly, "f :: exists a. Num a => a" would mean "for some type a which implements Num ...".  So "f :: a; f = 1" doesn't work because it doesn't restrict the type enough.  By restricting the type to "Num a => a", gain the ability to use the functions in the Num class, one of which is "fromInteger", which is called implicitly whenever you use a literal integer - that's what makes integer literals polymorphic in Haskell.  Similarly, "f = 3.14" would require "f :: Fractional a => a" because "3.14" implicitly calls "fromRational", a function defined in the Fractional type class.

-- James

PS.  Although some Haskell compilers support them as optional language extensions, "forall" and "exists" are not official Haskell syntax - just conventions that humans use to keep things straight when thinking about the types.


More information about the Beginners mailing list