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

Pet*_*ley 6 haskell fixpoint-combinators

我试图绕着固定点和递归定义弯曲.

这有效:

>>> take 10 $ let x = (0:x) in x
[0,0,0,0,0,0,0,0,0,0]
Run Code Online (Sandbox Code Playgroud)

这也是一样的,考虑到以下定义,这是有意义的fix:

>>> take 10 $ fix (\x -> (0:x))
[0,0,0,0,0,0,0,0,0,0]
Run Code Online (Sandbox Code Playgroud)

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

>>> take 10 $ fst $ let (u,v) = (0:v,1:u) in (u,v)
[0,1,0,1,0,1,0,1,0,1]
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

chi*_*chi 14

你要

take 10 $ fst $ fix (\ ~(u,v) -> (0:v,1:u))
                      ^^^
Run Code Online (Sandbox Code Playgroud)

这样才能使模式匹配懒惰.在let,LHS模式是隐式惰性/无可辩驳的.

在普通\(u,v) -> ...的情况下,在产生任何输出之前将需要lambda的参数 - 这使得函数太严格了fix.你需要的是什么

take 10 $ fst $ fix (\p -> (0:snd p,1:fst p))
Run Code Online (Sandbox Code Playgroud)

所以这个参数不是由lambda强制的(那里没有匹配的构造函数).惰性模式方法等同于fst/snd上述方法.

  • @redneb修正了.(双关语:-P) (3认同)