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.
Consider the expression that doesn’t work
ncan be any integer-y type, so it can be passed anIntegerorWordorInt.(>)has typeOrd a => a -> a -> Boolso both its left and right operand have to be of the same type.length xsreturns anIntso this type has to be that. But,ncan be anyIntegral, not necessarilyInt, so we need some way of allowingnto be converted to anInt. This is whatfromIntegraldoes (the fact that it also allowsnto be anyNumis basically irrelevant).We could expand the working version to look like:
which makes it clearer that we’re using a specialised version of
fromIntegral.(Note that
isLongerThanN n xs = fromIntegral (length xs) > nalso works, because it allows the result oflengthto match up with the type ofn.)