我不明白为什么以下功能有效:
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的类型。
答案 0 :(得分:12)
考虑不起作用的表达
isLongerThanN' :: Integral n => n -> [a] -> Bool
isLongerThanN' n xs = length xs > n
n
可以是任何整数y类型,因此可以传递Integer
或Word
或Int
。 (>)
的类型为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
的类型匹配。)