import Data.List(genericLength)
length' :: (Show a, Num n) => a -> n
length' = genericLength . show
1
Int 是积分的实例,但是,例如, Integer . 您的签名是 a -> a (其中 a 是 Integral ),这意味着结果的类型必须与输入的类型相同 . 因此,如果您将 length' 应用于 Int ,根据您的签名,结果应为 Int ,如果将其应用于 Integer ,则结果应为 Integer .
由于 length 产生 Int 作为结果, length' 的结果也将始终为 Int ,这与您的签名相矛盾 .
一个修复方法是将您的签名更改为 Integral a => a -> Int (或更通用的 Show a => a -> Int )或添加对 fromIntegral 的调用以将 Int 转换为适当类型的数字 .
2 回答
如果你写的东西如下:
这意味着该函数适用于
a
所在的a
. 这意味着使用length'
的程序员可以决定将其用作:length' :: Integer -> Integer
. 由于length
然而没有返回Integer
(但是Int
),Haskell无法提供这样的函数length'
.您的函数还有另一个问题:您在
a
上调用show
. 这意味着a
必须是Show
类的实例 . 所以你应该添加一个类型约束Show a
. 无需限制为Integral a
,因为您可以将该函数用于Show
的所有内容 . 所以类型签名应该是:如果您想让用户自由使用任何
Num n
作为输出类型,您可以使用genericLength :: Num n => [a] -> n函数:Int
是积分的实例,但是,例如,Integer
. 您的签名是a -> a
(其中a
是Integral
),这意味着结果的类型必须与输入的类型相同 . 因此,如果您将length'
应用于Int
,根据您的签名,结果应为Int
,如果将其应用于Integer
,则结果应为Integer
.由于
length
产生Int
作为结果,length'
的结果也将始终为Int
,这与您的签名相矛盾 .一个修复方法是将您的签名更改为
Integral a => a -> Int
(或更通用的Show a => a -> Int
)或添加对fromIntegral
的调用以将Int
转换为适当类型的数字 .