[Haskell-beginners] type error in sub-function

Brent Yorgey byorgey at seas.upenn.edu
Sat Feb 15 22:40:21 UTC 2014


On Sat, Feb 15, 2014 at 03:52:25PM -0600, James Toll wrote:
> 
> Again, thank you for this very helpful explanation of the problem, and I understand that Haskell doesn’t cast types automatically.  In fact I was relying on that as I built up my function.  What I guess really confused me was that this worked:
> 
> Prelude> filter (\y -> mod 36 y == 0) [2..(ceiling . sqrt) 36]
> [2,3,4,6]
> 
> while this didn’t.  
> 
> Prelude> let lower x = filter (\y -> mod x y == 0) [2..(ceiling . sqrt) x]
> Prelude> lower 36

This is sneaky: in the first example, there are two occurrences of the
number 36, and they have different types! Number literals are
polymorphic, that is, they can be any type which is an instance of the
Num class. The first 36 has type Integer, since it's constrained by
'mod' to be an instance of Integral, and GHC will pick the Integer
type by default.  The second 36, on the other hand, has type Double,
since sqrt requires a type which is an instance of Floating.

When you abstract this out into the function 'lower', however, the
argument x can only have one type, i.e. the two occurrences of x are
required to be the *same* type.

> 
> Since the former worked, I really expected the latter to work as well. 
> 
> > :t 36
> > 36 :: Num a => a
> 
> 
> I am still slightly confused about the type that I passed into the function. If the type of 36 is Numeric, that doesn’t seem to necessarily tell me that it is an Int.  Float and Double are listed under Numeric in the chart (https://www.haskell.org/onlinereport/classes.gif).  This seems like a really stupid question, but how do I know that I can’t pass a Numeric into a function like sqrt that is expecting a Float?

Note that Num (Numeric) is not a type, it is a type class.  It does
not make sense to say "the type of 36 is Numeric".  A better way to
say it is that "36 can have any type, as long as it is an instance of
the Num type class".

You *can* pass 36 into a function like sqrt, since anything which is
an instance of Floating is required to also be an instance of Num.

-Brent


More information about the Beginners mailing list