与Haskell类型推断混淆

时间:2012-04-29 03:11:19

标签: haskell type-inference

我不明白为什么以下功能有效:

isLongerThanN :: Integral n => n -> [a] -> Bool
isLongerThanN n xs = length xs > fromIntegral n

但以下情况并非如此:

isLongerThanN' :: Integral n => n -> [a] -> Bool
isLongerThanN' n xs = length xs > n

抛出错误

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

(我可能误解了)

如果有的话,我希望它是另一种方式,因为 fromIntegral 有效地扩展了变量n的类型。

1 个答案:

答案 0 :(得分:12)

考虑不起作用的表达

isLongerThanN' :: Integral n => n -> [a] -> Bool
isLongerThanN' n xs = length xs > n

n可以是任何整数y类型,因此可以传递IntegerWordInt(>)的类型为Ord a => a -> a -> Bool,因此其左右操作数必须属于同一类型。 length xs返回Int,因此此类型必须为此。但是,n可以是任何Integral,不一定是Int,因此我们需要某种方式允许n转换为Int。这就是fromIntegral所做的事情(事实上它也允许n为任何Num基本上无关紧要。)

我们可以将工作版本扩展为:

toInt :: Integral n => n -> Int
toInt = fromIntegral

isLongerThanN :: Integral n => n -> [a] -> Bool
isLongerThanN n xs = length xs > toInt n

这使我们更清楚地知道我们正在使用fromIntegral的专门版本。

(请注意isLongerThanN n xs = fromIntegral (length xs) > n也有效,因为它允许length的结果与n的类型匹配。)