Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 您如何实施;“显示”;递归跟踪?_Haskell_Tail Recursion - Fatal编程技术网

Haskell 您如何实施;“显示”;递归跟踪?

Haskell 您如何实施;“显示”;递归跟踪?,haskell,tail-recursion,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 你可以通过递归的方式来扭转

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

你可以通过递归的方式来扭转这条尾巴。看看wiki页面上的示例。

使用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(您的原始实现就是这样)而不是tail recursive

此函数的大部分时间将被左嵌套的
(++)
调用占用,这在其左参数中是
O(n)
。解决方案是使用a,这是延续传递样式本身的一种形式


另请参见,其中讨论了如何通过转换为CPS来实现高效算法,然后将连续体的结构转换为更具体的结构,以获得尾部递归解决方案。

我感兴趣的是,是否存在将具有多个递归分支的非尾部递归函数明显转换为尾部递归对应函数的情况。我认为你必须使用拉链才能保持它的效率,这是错误的吗?因为累积结构需要在每次尾部调用时进行深度编辑?CPS本质上使累积结构成为一种功能,其功能强大到足以“深度编辑”啊,好吧!这很合适,谢谢各位。Haskell的
showsPrec
不是通过让你们提供一个函数
a->ShowS
来解决这个问题吗?不确定,但我就是这么想的?@Alec
showsPrec
show
更有效,但它不是尾部递归的。然而,这是因为在Haskell中,
show
是尾部递归(参见luqui提到的corecursivity)是没有意义的。