为什么haskell的“修复”似乎与元组有问题?

时间:2016-09-11 19:01:55

标签: haskell

我试图绕着固定点和递归定义弯腰。

这有效:

>>> take 10 $ let x = (0:x) in x
[0,0,0,0,0,0,0,0,0,0]

这也是一样的,考虑到fix

的定义,这是有道理的
>>> take 10 $ fix (\x -> (0:x))
[0,0,0,0,0,0,0,0,0,0]

现在假设我开始乱搞递归定义的对:

>>> take 10 $ fst $ let (u,v) = (0:v,1:u) in (u,v)
[0,1,0,1,0,1,0,1,0,1]

好的,我应该能够用fix写出来,对吧?

>>> take 10 $ fst $ fix (\(u,v) -> (0:v,1:u))
*** Exception: <<loop>>

但它不起作用。除非我做出以下看似微不足道的改变:

>>> take 10 $ fst $ fix (\r -> let (u,v)=r in (0:v,1:u))
[0,1,0,1,0,1,0,1,0,1]

最后两个例子之间的关键区别是什么?

1 个答案:

答案 0 :(得分:14)

你想要

take 10 $ fst $ fix (\ ~(u,v) -> (0:v,1:u))
                      ^^^

以使模式匹配延迟。在let中,LHS模式是隐式惰性/无可辩驳的。

使用plain \(u,v) -> ...,在生成任何输出之前将要求lambda的参数 - 这使得函数对fix来说太严格了。你需要的是像

take 10 $ fst $ fix (\p -> (0:snd p,1:fst p))

因此lambda不强制参数(那里没有匹配的构造函数)。惰性模式方法等同于上面的fst/snd