2014-01-19 26 views
6

我的问题涉及回答另一个问题:https://stackoverflow.com/a/11766789/3212958是否< - 在Haskell do块中隐式强制类型?

在他的回答,ertes写入以下类型签名

select :: [a] -> [(a, [a])] 

然而,当select实际使用,ertes写入do内的以下阻止

(y, ys) <- select xs 

请帮我流下的元组(y, ys)怎样的选择,名字返回类型相匹配的一些光ly [(a, [a])]。 Haskell在某些时候强制类型? (Haskell曾经强制类型?)<-select返回的列表monad中提取类型的元组?

感谢, 最大

---编辑:---

@Lee提醒newbs试图推理类型的前desugar。在明确了>>=后,更清楚发生了什么事情。脱糖后,有问题的函数看起来像:

select xs >>= \(y, ys) -> fmap (y:) (perms (n - 1) ys) 

而对于名单,xs >>= f = concat (map f xs)。因此,在这种情况下更好的读取(y, ys)是作为映射到列表上的函数的签名。

+3

'select'返回一个列表。如果你写'a < - 选择xs',那么'a'是'select xs'的每个元素。如果你后来编写'func a',结果就是在'select xs'的每个元素上应用'func'的结果。这就是列表monad的定义方式。 'a < - 选择xs; func a'与'select xs >> = func'相同。绑定列表被定义为:'m >> = f = concat(map f m)',因此您正在编写'map func(select xs)'。哈斯克尔没有类型强制。 – user2407038

+0

@ user2407038这里有一些细微的技术性问题; “a”不是“每个元素”,“a”表示列表中的一个*(任意但特定)元素。 –

回答

13

do符号,

do x1 <- action1 
    action2 

被翻译成action1 >>= \x1 -> action2

这意味着如果action1具有用于一些单子m键入m a,然后x1具有类型a。这并不是真正的强制类型,而是将单个动作action1的值“拆包”并将其绑定到x1

4

(y, ys)是类型(b, c)

select返回类型是类型[(a, [a])]

的在<-的类型实际上dMonad m => m d的。所以我们可以写出以下类型的等式:

(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 
+1

'[](a,[] a)'如果你喜欢,Haskell实际上是有效的,或者甚至是[]((,)a([] a))。 –

+0

哦,我不知道'']'的类型构造函数可以这样使用,就像值构造函数一样。 – nponeccop

+0

是的,我也很惊喜地了解它。当然可以更容易地解释列表monad。 –

相关问题