gpt4 book ai didi

haskell - 类型声明有什么问题吗?

转载 作者:行者123 更新时间:2023-12-01 11:18:20 25 4
gpt4 key购买 nike

我正在阅读《Programming in 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 的参数值为真,函数 unfold p h t 生成空列表,否则生成非通过将函数 h 应用于此值以给出头部,以及函数 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 <b>Eq a =></b> Eq [a] where
...

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

Num 类型类暗示该类型也是Eq 类型。我们可以在这里做两件事:

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

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

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

关于haskell - 类型声明有什么问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47571066/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com