Inept
Inept

Reputation: 105

Confusion with Haskell type inference

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.

Upvotes: 5

Views: 744

Answers (1)

huon
huon

Reputation: 102006

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

Upvotes: 12

Related Questions