F# 树叶列表与连续尾递归
F# tree leaves to list with continuation tail-recursion
我有一棵有枝有叶的类型树。我想获得叶子值列表。到目前为止我只能数分支。
我的树:
type 'a tr =
| Leaf of 'a
| Branch of 'a tr * 'a tr
我的代码:
let getList (tr:float tr)=
let rec toList tree acc =
match tree with
| Leaf _ -> acc 0
| Branch (tl,tr) -> toList tl (fun vl -> toList tr (fun vr -> acc(vl+vr+1)))
toList tr id
输入:
let test=Branch (Leaf 1.2, Branch(Leaf 1.2, Branch(Branch(Leaf 4.5, Leaf 6.6), Leaf 5.4)))
getList test
因此,我想得到一个列表:
[1.2; 1.2; 4.5; 6.6; 5.4]
我尝试了一些与此类似的变体,但没有成功。
| Branch (tl,tr) -> toList tl (fun vl -> toList tr (fun vr -> (vl::vr)::acc))
toList tr []
如有任何帮助,我们将不胜感激。
这是由于你的延续函数 (acc) 的签名是 (int -> 'a)
如果你想得到一个展平列表,连续函数签名应该是 ('a list -> 'b)
let getList tree =
let rec toList tree cont =
match tree with
| Leaf a -> cont [a]
| Branch (left, right) ->
toList left (fun l ->
toList right (fun r ->
cont (l @ r)))
toList tree id
编辑;这应该更有效率
let getList tree =
let rec toList tree cont acc =
match tree with
| Leaf a -> cont (a :: acc)
| Branch (left, right) -> toList left (toList right cont) acc
toList tree id [] |> List.rev
请注意,您的树类型不能表示只有一个子节点的节点。类型应该是:
type Tree<'T> =
| Leaf of 'T
| OnlyOne of Tree<'T>
| Both of Tree<'T> * Tree<'T>
要将尾递归与延续一起使用,请使用延续函数,而不是accumulator:
let leaves tree =
let rec collect tree cont =
match tree with
| Leaf x -> cont [x]
| OnlyOne tree -> collect tree cont
| Both (leftTree, rightTree) ->
collect leftTree (fun leftAcc ->
collect rightTree (fun rightAcc ->
leftAcc @ rightAcc |> cont))
collect tree id
P/S:你的命名不太好:tr
含义太多。
我有一棵有枝有叶的类型树。我想获得叶子值列表。到目前为止我只能数分支。
我的树:
type 'a tr =
| Leaf of 'a
| Branch of 'a tr * 'a tr
我的代码:
let getList (tr:float tr)=
let rec toList tree acc =
match tree with
| Leaf _ -> acc 0
| Branch (tl,tr) -> toList tl (fun vl -> toList tr (fun vr -> acc(vl+vr+1)))
toList tr id
输入:
let test=Branch (Leaf 1.2, Branch(Leaf 1.2, Branch(Branch(Leaf 4.5, Leaf 6.6), Leaf 5.4)))
getList test
因此,我想得到一个列表:
[1.2; 1.2; 4.5; 6.6; 5.4]
我尝试了一些与此类似的变体,但没有成功。
| Branch (tl,tr) -> toList tl (fun vl -> toList tr (fun vr -> (vl::vr)::acc))
toList tr []
如有任何帮助,我们将不胜感激。
这是由于你的延续函数 (acc) 的签名是 (int -> 'a) 如果你想得到一个展平列表,连续函数签名应该是 ('a list -> 'b)
let getList tree =
let rec toList tree cont =
match tree with
| Leaf a -> cont [a]
| Branch (left, right) ->
toList left (fun l ->
toList right (fun r ->
cont (l @ r)))
toList tree id
编辑;这应该更有效率
let getList tree =
let rec toList tree cont acc =
match tree with
| Leaf a -> cont (a :: acc)
| Branch (left, right) -> toList left (toList right cont) acc
toList tree id [] |> List.rev
请注意,您的树类型不能表示只有一个子节点的节点。类型应该是:
type Tree<'T> =
| Leaf of 'T
| OnlyOne of Tree<'T>
| Both of Tree<'T> * Tree<'T>
要将尾递归与延续一起使用,请使用延续函数,而不是accumulator:
let leaves tree =
let rec collect tree cont =
match tree with
| Leaf x -> cont [x]
| OnlyOne tree -> collect tree cont
| Both (leftTree, rightTree) ->
collect leftTree (fun leftAcc ->
collect rightTree (fun rightAcc ->
leftAcc @ rightAcc |> cont))
collect tree id
P/S:你的命名不太好:tr
含义太多。