在Haskell do块中隐式强制类型?
我的问题与另一个问题的答案有关:https://stackoverflow.com/a/11766789/3212958
在他的回答中,ertes写下了以下类型的签名
select :: [a] -> [(a, [a])]
但是,实际使用select
时,ertes在do
块中写入以下内容
(y, ys) <- select xs
请帮助我了解元组(y, ys)
匹配select的返回类型,即[(a, [a])]
。 Haskell在某些时候强制类型? (是否曾经哈斯克尔强制类型?)是<-
提取类型的元组(a, [a])
从列表单子是select
回报?
谢谢,马克斯
---编辑:---
@Lee提醒新人在尝试推理类型之前先解开它。 在>>=
明确之后,更清楚发生了什么事情。 解除绑定后,这个函数看起来像:
select xs >>= (y, ys) -> fmap (y:) (perms (n - 1) ys)
对于列表, xs >>= f = concat (map f xs)
。 因此(y, ys)
在这种情况下更好地阅读(y, ys)
作为函数的签名来映射列表。
在do
记号,
do x1 <- action1
action2
被翻译成action1 >>= x1 -> action2
这意味着如果action1
对某些monad m
有类型ma
,那么x1
类型为a
。 这不是真正强制类型,而是将monadic action action1
的值“解压”并将其绑定到x1
。
(y, ys)
是类型(b, c)
select
的返回类型是[(a, [a])]
在<-
类型实际上是d
和Monad m => md
。 所以我们可以写出以下类型的等式:
(b, c) ~ d
[(a, [a])] ~ Monad m => m d
解决起来很简单。 首先将第一个方程中的d
代入第二个方程:
[(a, [a])] ~ Monad m => m (b, c)
现在看看发生了什么,我将使用[]类型构造函数的前缀形式(它不是有效的haskell,但你应该明白):
[] (a, [a]) ~ Monad m => m ( b, c)
所以
m ~ []
(a, [a]) ~ (b, c)
此时编译器会检查instance Monad [a]
存在。 其余的很简单:
a ~ b
[a] ~ c
链接地址: http://www.djcxy.com/p/43035.html