Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.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
F# 如何使用尾部递归实现自己的List.partition?_F#_Tail Recursion_Continuation Passing - Fatal编程技术网

F# 如何使用尾部递归实现自己的List.partition?

F# 如何使用尾部递归实现自己的List.partition?,f#,tail-recursion,continuation-passing,F#,Tail Recursion,Continuation Passing,我正试图为F#练习编写我自己的List.partition函数。这是我第一次(天真的)尝试: 这是可行的,但不是尾部递归。我进行了第二次尝试,使用累加器实现尾部递归: let mypartition_accumulator func list = let rec helper acc listinner = match listinner with | head::tail -> let a,b = acc

我正试图为F#练习编写我自己的List.partition函数。这是我第一次(天真的)尝试:

这是可行的,但不是尾部递归。我进行了第二次尝试,使用累加器实现尾部递归:

let mypartition_accumulator func list =
    let rec helper acc listinner =
        match listinner with
        | head::tail ->
            let a,b = acc
            let newacc = if func head then (head::a,b) else (a,head::b)
            helper newacc tail
        | _ -> acc
    helper ([],[]) list
严格地说,这是有效的:它划分了列表。问题是这会颠倒列表的顺序。我明白了:

let mylist = [1;2;3;4;5;6;7;8]
let partitioned = mypartition_accumulator (fun x -> x % 2 = 0) mynums
//partitioned is now ([8; 6; 4; 2], [7; 5; 3; 1])
//I want partitioned to be ([2; 4; 6; 8], [1; 3; 5; 7])

我认为我可以使用延续传递来编写一个尾部递归分区函数,它不会反转列表元素,但我并不真正理解延续传递(我已经读了很多关于它的书)。如何使用tail recursive编写分区并保持列表元素的有序性?

这里有一个CPS版本,但是
list.rev
是一种方法(参见此)


这里有一个CPS版本,但是
List.rev
是一个不错的选择(参见此)


这里有一个CPS版本,但是
List.rev
是一个不错的选择(参见此)


这里有一个CPS版本,但是
List.rev
是一个不错的选择(参见此)


虽然这个问题已经得到了回答,但值得一试解释。基于累加器的尾部递归版本基本上是从左向右折叠的,因此需要反转

let fold folder state list : 'State =
    let rec aux state = function
    | [] -> state
    | h:'T::t -> aux (folder state h) t
    aux state list
// val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State

let partitionFold p = 
    fold (fun (a, b) h -> if p h then h::a, b else a, h::b) ([], [])
    >> fun (a, b) -> List.rev a, List.rev b

partitionFold (fun x -> x % 2 = 0) [0..10] 
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])
fold
的签名和功能现在与标准库中的
List.fold
完全相同

相反,延续传递样式的版本相当于
foldBack
(参见
List.foldBack
)。它从右到左递归迭代(首先是最后一个元素),从而立即获得所需的顺序

let foldBack folder list state : 'State =
    let rec aux k = function
    | [] -> k state
    | h:'T::t -> aux (folder h >> k) t
    aux id list
// val foldBack :
//     folder:('T -> 'State -> 'State) -> list:'T list -> state:'State -> 'State

let partitionFoldBack p list = 
    foldBack (fun h (a, b) -> if p h then h::a, b else a, h::b) list ([], [])

partitionFoldBack (fun x -> x % 2 = 0) [0..10] 
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])

虽然这个问题已经得到了回答,但值得一试解释。基于累加器的尾部递归版本基本上是从左向右折叠的,因此需要反转

let fold folder state list : 'State =
    let rec aux state = function
    | [] -> state
    | h:'T::t -> aux (folder state h) t
    aux state list
// val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State

let partitionFold p = 
    fold (fun (a, b) h -> if p h then h::a, b else a, h::b) ([], [])
    >> fun (a, b) -> List.rev a, List.rev b

partitionFold (fun x -> x % 2 = 0) [0..10] 
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])
fold
的签名和功能现在与标准库中的
List.fold
完全相同

相反,延续传递样式的版本相当于
foldBack
(参见
List.foldBack
)。它从右到左递归迭代(首先是最后一个元素),从而立即获得所需的顺序

let foldBack folder list state : 'State =
    let rec aux k = function
    | [] -> k state
    | h:'T::t -> aux (folder h >> k) t
    aux id list
// val foldBack :
//     folder:('T -> 'State -> 'State) -> list:'T list -> state:'State -> 'State

let partitionFoldBack p list = 
    foldBack (fun h (a, b) -> if p h then h::a, b else a, h::b) list ([], [])

partitionFoldBack (fun x -> x % 2 = 0) [0..10] 
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])

虽然这个问题已经得到了回答,但值得一试解释。基于累加器的尾部递归版本基本上是从左向右折叠的,因此需要反转

let fold folder state list : 'State =
    let rec aux state = function
    | [] -> state
    | h:'T::t -> aux (folder state h) t
    aux state list
// val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State

let partitionFold p = 
    fold (fun (a, b) h -> if p h then h::a, b else a, h::b) ([], [])
    >> fun (a, b) -> List.rev a, List.rev b

partitionFold (fun x -> x % 2 = 0) [0..10] 
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])
fold
的签名和功能现在与标准库中的
List.fold
完全相同

相反,延续传递样式的版本相当于
foldBack
(参见
List.foldBack
)。它从右到左递归迭代(首先是最后一个元素),从而立即获得所需的顺序

let foldBack folder list state : 'State =
    let rec aux k = function
    | [] -> k state
    | h:'T::t -> aux (folder h >> k) t
    aux id list
// val foldBack :
//     folder:('T -> 'State -> 'State) -> list:'T list -> state:'State -> 'State

let partitionFoldBack p list = 
    foldBack (fun h (a, b) -> if p h then h::a, b else a, h::b) list ([], [])

partitionFoldBack (fun x -> x % 2 = 0) [0..10] 
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])

虽然这个问题已经得到了回答,但值得一试解释。基于累加器的尾部递归版本基本上是从左向右折叠的,因此需要反转

let fold folder state list : 'State =
    let rec aux state = function
    | [] -> state
    | h:'T::t -> aux (folder state h) t
    aux state list
// val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State

let partitionFold p = 
    fold (fun (a, b) h -> if p h then h::a, b else a, h::b) ([], [])
    >> fun (a, b) -> List.rev a, List.rev b

partitionFold (fun x -> x % 2 = 0) [0..10] 
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])
fold
的签名和功能现在与标准库中的
List.fold
完全相同

相反,延续传递样式的版本相当于
foldBack
(参见
List.foldBack
)。它从右到左递归迭代(首先是最后一个元素),从而立即获得所需的顺序

let foldBack folder list state : 'State =
    let rec aux k = function
    | [] -> k state
    | h:'T::t -> aux (folder h >> k) t
    aux id list
// val foldBack :
//     folder:('T -> 'State -> 'State) -> list:'T list -> state:'State -> 'State

let partitionFoldBack p list = 
    foldBack (fun h (a, b) -> if p h then h::a, b else a, h::b) list ([], [])

partitionFoldBack (fun x -> x % 2 = 0) [0..10] 
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])


最好在返回累加器之前调用
List.rev
。在最后的递归调用中反转列表。最好在返回累加器之前调用
List.rev
。在最后的递归调用中反转列表。最好在返回累加器之前调用
List.rev
。在最后的递归调用中反转列表。最好在返回累加器之前调用
List.rev
。在最后的递归调用中反转列表。谢谢。我需要一段时间才能弄明白这是怎么回事。@Danial,你能解释一下为什么你的解决方案中有
xs
?我从您的解决方案中显示的位置删除了
、xs
,同时删除了
|>fst
,代码仍然可以正常工作。@user2023861:这是一个错误。我从参考答案中复制/调整了代码,但没有找到。已经修好了。接得好,谢谢。我需要一段时间才能弄明白这是怎么回事。@Danial,你能解释一下为什么你的解决方案中有
xs
?我从您的解决方案中显示的位置删除了
、xs
,同时删除了
|>fst
,代码仍然可以正常工作。@user2023861:这是一个错误。我从参考答案中复制/调整了代码,但没有找到。已经修好了。接得好,谢谢。我需要一段时间才能弄明白这是怎么回事。@Danial,你能解释一下为什么你的解决方案中有
xs
?我从您的解决方案中显示的位置删除了
、xs
,同时删除了
|>fst
,代码仍然可以正常工作。@user2023861:这是一个错误。我从参考答案中复制/调整了代码,但没有找到。已经修好了。接得好,谢谢。我需要一段时间才能弄明白这是怎么回事。@Danial,你能解释一下为什么你的解决方案中有
xs
?我从您的解决方案中显示的位置删除了
、xs
,同时删除了
|>fst
,代码仍然可以正常工作。@user2023861:这是一个错误。我从参考答案中复制/调整了代码,但没有找到。已经修好了。抢手货