[Haskell-beginners] question on types

Jake Penton djp at arqux.com
Fri Jul 29 15:49:14 CEST 2011


On 2011-07-29, at 9:23 AM, James Cook wrote:

> 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.

Well, there have been a couple of answers on this thread that suggest that a constraint/context will work. But this does not clear things up entirely for me. I probably do not understand your answer. But adding a constraint by itself does not of itself change things, although perhaps you are not suggesting that it would. 

For example, this does not compile:

f :: Fractional a => a
f = 3.14

This does:

class Foo a where
    f :: Fractional a => a

instance Foo Float where
    f = 3.14

So I infer that the reason that my example int the original post compiles is something other than merely the presence of the constraint. This compiles:

f :: Num a => a
f = 1

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/beginners/attachments/20110729/b35c46f7/attachment.htm>


More information about the Beginners mailing list