【发布时间】:2016-12-21 18:56:16
【问题描述】:
我正在尝试在 Haskell 中编写一个简单的工具作为学习练习,但遇到了一些我无法弄清楚的事情。这是一个简单的示例来说明它。
idMap :: a -> a
idMap x = map id x
main = do
print $ idMap [1, 2]
根据我的理解,这个例子应该在运行时编译并打印[1, 2]。但是,如果编译失败并显示以下消息:
source_file.hs:2:18: error:
• Couldn't match expected type ‘[b0]’ with actual type ‘a’
‘a’ is a rigid type variable bound by
the type signature for:
idMap :: forall a. a -> a
at source_file.hs:1:10
• In the second argument of ‘map’, namely ‘x’
In the expression: map id x
In an equation for ‘idMap’: idMap x = map id x
• Relevant bindings include
x :: a
(bound at source_file.hs:2:7)
idMap :: a -> a
(bound at source_file.hs:2:1)
这有点道理,因为map 的签名是(a -> b) -> [a] -> [b],所以输入类型不一定与输出类型相同,但id 的签名是a -> a,所以它肯定遵循map id 的签名是 (a -> a) -> [a] -> [a]?
我不太明白的第二部分是为什么这是一个例外,因为所有类型(a 和b 如上所述)都是Integer。对我来说,由于idMap 的签名是a -> a,这对我来说是有意义的,如果在预期输出类型与输入类型不同的情况下使用它,则应该只存在编译异常。
最后,我怎样才能让这段代码真正起作用?我的真实代码有点复杂,我依赖输出类型匹配代码中其他地方的输入类型,所以我不想更改idMap 的签名,我想知道我需要做什么用那个签名写一个函数。
【问题讨论】:
-
map id的类型是[a] -> [a],而您将其指定为a -> a。