简体   繁体   中英

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM