首页 文章

使用foldr的Haskell Type类

提问于
浏览
1

我使用foldr编写了一个函数来确定列表或字符串的长度 . 我有点困惑为什么Haskell确定类型类是Num . 当然字符串不包括在这个类中?但是Haskell坚持认为必须这样,否则函数将无效 . 有人可以帮助澄清这是为什么吗?

myLength' :: (Num a) => [a] -> Int
myLength' xs = foldr (\x acc -> 1 + acc) 0 xs

1 回答

  • 3

    我认为您的类型签名可能因您的声明而过于具体 . 这是我在GHCi中得到的:

    > :t foldr
    foldr :: (a -> b -> b) -> b -> [a] -> b
    
    > :t foldr (\x acc -> acc + 1)
    ... :: Num b => b -> [a] -> b
    

    +Num 约束的来源 . 它仅适用于 b 类型,因为 acc 的类型与 b 统一 . 没有进一步的限制因为我们没有对 x :: a 做任何事情 .

    > :t foldr (\x acc -> acc + 1) 0
    ... :: Num b => [a] -> b
    

    0 轻松与 Num b => b 统一,除了我们掉箭之外没有任何变化 .

    > :t \xs -> foldr (\x acc -> acc + 1) 0 xs
    ... :: Num b => [a] -> b
    

    我们引入了一个没有特定类型的参数 xs ,它很容易与 [a] 统一 . 没有什么变化 . 所以我们的最终类型应该是

    myLength :: (Num b) => [a] -> b
    myLength = foldr (\_ acc -> 1 + acc) 0
    

    这确实适用于字符串 . myLength "hello" => 5 等等 .

    正如Lee在评论中提到的那样, foldr 的类型在GHC 7.10中更改为 Foldable t => (a -> b -> b) -> b -> t a -> b ,作为Foldable Traversable in Prelude Proposal的一部分,允许 foldr 用于许多不同的数据结构而不是单独的列表 . 在GHC 7.10上,那么你的函数确实会有 myLength :: (Foldable t, Num b) => t a -> b 的类型推断 . 注意 (Foldable t) => t a 如何概括 [a] .

    HOORAY TYPES

相关问题