5

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

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 的类型。

4

1 回答 1

12

考虑不起作用的表达式

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

n可以是任何整数-y 类型,因此可以传递IntegerorWordInt. (>)有类型Ord a => a -> a -> Bool,所以它的左操作数和右操作数必须是相同的类型。length xs返回一个Int所以这个类型必须是那个。但是,n可以是 any Integral,不一定是Int,所以我们需要某种方式来允许n转换为Int。这就是fromIntegral它的作用(事实上它也允许n是 anyNum基本上是无关紧要的)。

我们可以将工作版本扩展为如下所示:

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

于 2012-04-29T03:24:06.667 回答