[英]Understanding function definitions and types in Haskell
我试图在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
id
a -> a
肯定地说map id
会有(a -> a) -> [a] -> [a]
的签名吗?
我不太明白的第二部分是为什么这是一个例外,因为所有类型(如上所述的a
和b
)都是Integer
。 对我来说有意义的是,由于idMap
的签名是a -> a
,如果在输出类型与输入类型不同的情况下使用它,则应该只有编译异常。
最后,我将如何使这段代码真正起作用? 我真正的代码有点复杂,我依赖于输出类型匹配代码中其他地方的输入类型,所以我不想更改idMap
的签名,我想知道我需要做什么来写一个具有该签名的功能。
您正在将idMap
应用于列表。 因此,我们知道参数类型应该是一些列表类型。 此外,您希望返回类型是一个列表( [1,2]
),因此返回类型也应该是一个列表。 由于id
函数是完全多态的( a -> a
),我们可以map
它map
到任何类型a
的列表,并返回相同类型a
的项列表。 因此,您的最终类型签名应为[a] -> [a]
。
关于你的第二个问题,虽然参数类型和返回类型都是相同的,但对于所有类型a
,类型为a -> a
不是真的。 根据map
的类型签名, idMap
必须接受list参数。 我们可以为比必要的约束更多的函数声明类型签名,但不能更少。
你的idMap
实现......
idMap x = map id x
...涉及在x
上应用map id
。 因此, x
必须是一个列表。
GHCi> :t map id
map id :: [b] -> [b]
这将工作得很好:
idMap :: [a] -> [a]
idMap x = map id x
请注意,由于使用了id
, x
和idMap x
确实具有相同的类型(就像它们的元素一样),正如您所期望的那样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.