I have a pretty general question about Haskell's type system. I'm trying to become familiar with it, and I have the following function:
getN :: Num a => a
getN = 5.0 :: Double
When I try to compile this, I get the following error:
Couldn't match expected type `a' against inferred type `Double'
`a' is a rigid type variable bound by
the type signature for `getN' at Perlin.hs:15:12
In the expression: 5.0 :: Double
In the definition of `getN': getN = 5.0 :: Double
As I understand this, the function is set up to "return" a type in the class Num. Double is in this class (http://www.zvon.org/other/haskell/Outputprelude/Num_c.html), so I would have expected that it would be okay to "return" a Double in this case.
Can someone explain this please?
A function with signature
Num a => a
is expected to work for any type in the classNum
. The implementation5.0 :: Double
just works for one type, not for all types of the class, so the compiler complains.An example of a generic function would be:
This works for any type that is a
Num
. It works for doubles, integers and whatever other numbers you want to use. Because of that it can have a generic type signature that just requires the parameter to be in classNum
. (Type classNum
is necessary because the function uses multiplication with*
, which is defined there)Check out Existentially quantified types.
One way to solve it would be to define a new data type
You'll need
-XExistentialQuantification
to get this to work.Now you can write something like
You can also define a
NumBox
-list asTo add to sth's answer: Haskell is not object-oriented. It's not true that
Double
is a subclass ofNum
, so you cannot return aDouble
if you promise to return a polymorphicNum
value, like you can in, say, Java.When you write
getN :: Num a => a
you promise to return a value that is fully polymorphic within theNum
constraint. Effectively this means that you can only use functions from theNum
type class, such as+
,*
,-
andfromInteger
.