Nic*_*Lee 3 haskell higher-order-functions
我正在阅读"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
Run Code Online (Sandbox Code Playgroud)
(直接从练习题中获取)unfold p h t如果谓词p对参数值为true,则函数生成空列表,否则通过将函数h应用于此值以给出头部而t生成非空列表,并生成另一个函数以生成另一个以相同的方式递归处理的参数,以生成列表的尾部.
我检查了我的实现,mapinc它看起来很好:
*Main> mapinc [1,2,3]
[2,3,4]
Run Code Online (Sandbox Code Playgroud)
但是,在我添加类型声明后:
mapinc :: Num a => [a] -> [a]
mapinc = unfold (==[]) ((+1).head) tail
Run Code Online (Sandbox Code Playgroud)
然后在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 | ^^^^
Run Code Online (Sandbox Code Playgroud)
任何线索为什么会发生?
你的签名太宽泛了.你写的谓词是== [].Haskell只能检查两个列表是否相等,是否也可以检查列表的元素.在源代码中我们看到类似于:
instance Eq a => Eq [a] where
...Run Code Online (Sandbox Code Playgroud)
是的,在这里我们永远不会检查两个项目的相等性,因为我们检查空列表,但编译器当然不知道:它只是看到为了检查两个列表是否相等,我们需要能够检查元素是否相等.
该Num类型类并没有暗示类型也是一个Eq类型.我们可以在这做两件事:
将Eq类型约束添加到签名:
mapinc :: (Eq a, Num a) => [a] -> [a]
mapinc = unfold (==[]) ((+1).head) tailRun Code Online (Sandbox Code Playgroud)更优雅:不要依赖于我们需要能够比较元素的事实,而是使用null :: [a] -> Bool(一种检查列表是否为空的函数):
mapinc :: Num a => [a] -> [a]
mapinc = unfold null ((+1).head) tailRun Code Online (Sandbox Code Playgroud)| 归档时间: |
|
| 查看次数: |
55 次 |
| 最近记录: |