你如何实现" show"尾递归?

时间:2015-07-24 01:29:17

标签: haskell tail-recursion

Haskell的show通常以递归方式实现:

data Tree = Node Tree Tree | Leaf

show' (Node left right) = "(Node " ++ show' left ++ " " ++ show' right ++ ")"
show' Leaf              = "Leaf"

main = putStrLn $ show' (Node (Node Leaf Leaf) Leaf)

如何使用尾递归实现show

2 个答案:

答案 0 :(得分:6)

使用CPS,如M. Shaw所述。

show' :: Tree -> String
show' = \tree -> go tree id
    where
    go (Node left right) c = 
      go left (\l -> go right (\r -> c ("(Node " ++ l ++ " " ++ r ++ ")")))
    go Leaf c = c "Leaf"

重要的是要记住,在许多情况下,Haskell的懒惰消除了对尾递归的需要。在这种情况下,尾递归版必须遍历整个树,然后才能返回任何输入部分。尝试使用每个版本显示无限树。当以惰性语言返回诸如String之类的惰性结构时,最好是corecursive(与原始实现相比)而不是尾递归。

此函数的大部分时间都会被左嵌套(++)调用占用,其左侧参数为O(n)。解决方案是使用difference list,这是一种延续传递方式本身。

另见Continuation-Based Program Transformation Strategies,其中讨论了如何通过转换为CPS来获得有效的算法,然后将延续的结构转换为更具体的结果,以达到尾递归解决方案。

答案 1 :(得分:4)

你可以通过Continuation passing style转发这个尾递归。看看维基页面上的例子。