I don't understand why the following function works:
isLongerThanN :: Integral n => n -> [a] -> Bool
isLongerThanN n xs = length xs > fromIntegral n
but the following doesn't:
isLongerThanN' :: Integral n => n -> [a] -> Bool
isLongerThanN' n xs = length xs > n
which throws the error
Could not deduce (n ~ Int)
from the context (Integral n)
bound by the type signature for
isLongerThanN' :: Integral n => n -> [a] -> Bool
at blah.hs:140:1-35
`n' is a rigid type variable bound by
the type signature for
isLongerThanN' :: Integral n => n -> [a] -> Bool
at blah.hs:140:1
In the second argument of `(>)', namely `n'
In the expression: length xs > n
In an equation for `isLongerThanN'':
isLongerThanN' n xs = length xs > n
(which I've likely misunderstood)
If anything, I would expect it to be the other way around, since fromIntegral is effectively broadening variable n's type.
Type inference is the process by which Haskell guesses the types for variables and functions, without you needing to specify these types explicitly. Many functional languages feature type inference. There is lots of theory behind type inference - Hindley-Milner type systems and Unification.
() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .
Consider the expression that doesn't work
isLongerThanN' :: Integral n => n -> [a] -> Bool
isLongerThanN' n xs = length xs > n
n
can be any integer-y type, so it can be passed an Integer
or Word
or Int
. (>)
has type Ord a => a -> a -> Bool
so both its left and right operand have to be of the same type. length xs
returns an Int
so this type has to be that. But, n
can be any Integral
, not necessarily Int
, so we need some way of allowing n
to be converted to an Int
. This is what fromIntegral
does (the fact that it also allows n
to be any Num
is basically irrelevant).
We could expand the working version to look like:
toInt :: Integral n => n -> Int
toInt = fromIntegral
isLongerThanN :: Integral n => n -> [a] -> Bool
isLongerThanN n xs = length xs > toInt n
which makes it clearer that we're using a specialised version of fromIntegral
.
(Note that isLongerThanN n xs = fromIntegral (length xs) > n
also works, because it allows the result of length
to match up with the type of n
.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With