【问题标题】:Why does haskell's `fix` seem to have trouble with tuples?为什么 haskell 的 `fix` 似乎对元组有问题?
【发布时间】:2017-01-19 06:12:48
【问题描述】:

我正试图绕着固定点和递归定义低头。

这行得通:

>>> 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]

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

【问题讨论】:

    标签: haskell fixpoint-combinators


    【解决方案1】:

    你想要

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

    使模式匹配变得懒惰。在let 中,LHS 模式是隐含的惰性/无可辩驳的。

    对于普通的\(u,v) -&gt; ...,将在产生任何输出之前要求lambda 的参数——这使得函数对于fix 来说过于严格。你需要的是类似的东西

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

    这样参数就不会被 lambda 强制(没有构造函数可以匹配)。惰性模式方法等价于上面的fst/snd

    【讨论】:

    • 应该是\(~(u,v))\ ~(u,v)
    • @redneb 已修复。 (双关语:-P)
    猜你喜欢
    • 2011-10-13
    • 1970-01-01
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-27
    • 2011-03-14
    相关资源
    最近更新 更多