首页 文章

匹配积分与Int(Haskell)

提问于
浏览
1

我是Haskell的新手,我试图获得10号基数的长度,所以我创建了长度函数:

length' :: (Integral a) => a -> a
length' a = length $ show a

但是Haskell给了我"Couldn't match type"错误,因为 length 返回Int . 我不明白为什么它给我一个错误,因为Int是Integral的一个实例...

2 回答

  • 1

    如果你写的东西如下:

    length' :: (Integral a) => a -> a
    

    这意味着该函数适用于 a 所在的 a . 这意味着使用 length' 的程序员可以决定将其用作: length' :: Integer -> Integer . 由于 length 然而没有返回 Integer (但是 Int ),Haskell无法提供这样的函数 length' .

    您的函数还有另一个问题:您在 a 上调用 show . 这意味着 a 必须是 Show 类的实例 . 所以你应该添加一个类型约束 Show a . 无需限制为 Integral a ,因为您可以将该函数用于 Show 的所有内容 . 所以类型签名应该是:

    length' :: Show a => a -> Int
    length' = length . show
    

    如果您想让用户自由使用任何 Num n 作为输出类型,您可以使用genericLength :: Num n => [a] -> n函数:

    import Data.List(genericLength)
    
    length' :: (Show a, Num n) => a -> n
    length' = genericLength . show
    
  • 1

    Int 是积分的实例,但是,例如, Integer . 您的签名是 a -> a (其中 aIntegral ),这意味着结果的类型必须与输入的类型相同 . 因此,如果您将 length' 应用于 Int ,根据您的签名,结果应为 Int ,如果将其应用于 Integer ,则结果应为 Integer .

    由于 length 产生 Int 作为结果, length' 的结果也将始终为 Int ,这与您的签名相矛盾 .

    一个修复方法是将您的签名更改为 Integral a => a -> Int (或更通用的 Show a => a -> Int )或添加对 fromIntegral 的调用以将 Int 转换为适当类型的数字 .

相关问题