繁体   English   中英

类型声明有什么问题吗?

[英]Anything wrong with the type declaration?

我正在阅读“Haskell编程”一书。 一个练习要求我使用高阶函数定义map f 我选择定义map (+1) ,如下所示:

unfold p h t x | p x       = []
               | otherwise = h x : unfold p h t (t x)

-- equivalent to `map (+1)`
mapinc = unfold (==[]) ((+1).head) tail

(直接来自练习题)如果谓词p为参数值为true,则函数unfold pht生成空列表,否则通过将函数h应用于此值来生成非空列表以给出头部,并且function t生成另一个参数,以相同的方式递归处理以生成列表的尾部。

我检查了mapinc实现,看起来很好:

*Main> mapinc [1,2,3]
[2,3,4]

但是,在我添加类型声明后:

mapinc :: Num a => [a] -> [a]
mapinc = unfold (==[]) ((+1).head) tail

然后在WinGHCi中重新加载脚本,它会出现以下错误:

• Could not deduce (Eq a) arising from a use of ‘==’
  from the context: Num a
    bound by the type signature for:
               mapinc :: forall a. Num a => [a] -> [a]
    at D:\7a.hs:4:1-29
  Possible fix:
    add (Eq a) to the context of
      the type signature for:
        mapinc :: forall a. Num a => [a] -> [a]
• In the first argument of ‘unfold’, namely ‘(== [])’
  In the expression: unfold (== []) ((+ 1) . head) tail
  In an equation for ‘mapinc’:
      mapinc = unfold (== []) ((+ 1) . head) tail
  |
5 | mapinc = unfold (==[]) ((+1).head) tail   |                  ^^^^

任何线索为什么会发生?

你的签名太宽泛了 你写的谓词是== [] Haskell只能检查两个列表是否相等,是否也可以检查列表的元素 在源代码中我们看到类似于:

instance Eq a => Eq [a] where
    ...

是的,在这里我们永远不会检查两个项目的相等性,因为我们检查空列表,但编译器当然不知道:它只是看到为了检查两个列表是否相等,我们需要能够检查元素是否相等。

Num类型类并不意味着该类型也是一个Eq类型。 我们可以在这做两件事:

  1. Eq类型约束添加到签名:

     mapinc :: (Eq a, Num a ) => [a] -> [a] mapinc = unfold (==[]) ((+1).head) tail 
  2. 更优雅:不要依赖于我们需要能够比较元素的事实,而是使用null :: [a] -> Bool (一个检查列表是否为空的函数):

     mapinc :: Num a => [a] -> [a] mapinc = unfold null ((+1).head) tail 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM