Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.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# 折叠和减少之间的区别?_F#_Functional Programming_Reduce_Fold - Fatal编程技术网

F# 折叠和减少之间的区别?

F# 折叠和减少之间的区别?,f#,functional-programming,reduce,fold,F#,Functional Programming,Reduce,Fold,试图学习F#,但在试图区分和时感到困惑。Fold似乎起作用,但需要一个额外的参数。这两项职能的存在是否有正当的理由,或者它们的存在是为了适应不同背景的人?(例如:字符串和C#中的字符串) 以下是从示例复制的代码段: let sumAList list = List.reduce (fun acc elem -> acc + elem) list let sumAFoldingList list = List.fold (fun acc elem -> acc + e

试图学习F#,但在试图区分和时感到困惑。Fold似乎起作用,但需要一个额外的参数。这两项职能的存在是否有正当的理由,或者它们的存在是为了适应不同背景的人?(例如:字符串和C#中的字符串)

以下是从示例复制的代码段:

let sumAList list =
    List.reduce (fun acc elem -> acc + elem) list

let sumAFoldingList list =
    List.fold (fun acc elem -> acc + elem) 0 list

printfn "Are these two the same? %A " 
             (sumAList [2; 4; 10] = sumAFoldingList [2; 4; 10])

Fold
采用累加器的显式初始值,而
reduce
使用输入列表的第一个元素作为累加器的初始值

这意味着累加器和结果类型必须与列表元素类型匹配,而它们可以在
折叠方面有所不同,因为累加器是单独提供的。这反映在以下类型中:

List.fold : ('State -> 'T -> 'State) -> 'State -> 'T list -> 'State
List.reduce : ('T -> 'T -> 'T) -> 'T list -> 'T

此外,
reduce
在空输入列表上抛出异常。

除了Lee所说的,您可以根据
fold
定义
reduce
,但不(容易)相反:

let reduce f list = 
  match list with
  | head::tail -> List.fold f head tail
  | [] -> failwith "The list was empty!"
fold
为累加器获取一个明确的初始值这一事实也意味着
fold
函数的结果可以具有与列表中的值类型不同的类型。例如,您可以使用
string
类型的累加器将列表中的所有数字连接到文本表示中:

[1 .. 10] |> List.fold (fun str n -> str + "," + (string n)) ""
使用
reduce
时,累加器的类型与列表中的值的类型相同-这意味着如果您有一个数字列表,则结果必须是一个数字。要实现上一个示例,您必须先将数字转换为
字符串
,然后再累加:

[1 .. 10] |> List.map string
          |> List.reduce (fun s1 s2 -> s1 + "," + s2)

让我们看看他们的签名:

> List.reduce;;
val it : (('a -> 'a -> 'a) -> 'a list -> 'a) = <fun:clo@1>
> List.fold;;
val it : (('a -> 'b -> 'a) -> 'a -> 'b list -> 'a) = <fun:clo@2-1>
如果没有任何合理的蓄能器,则更方便:

// Intersect a list of sets altogether
let intersectMany xss = List.reduce (fun acc xs -> Set.intersect acc xs) xss
一般来说,
fold
对于任意类型的累加器更强大:

// Reverse a list using an empty list as the accumulator
let rev xs = List.fold (fun acc x -> x::acc) [] xs

fold
reduce
更有价值。您可以根据
折叠定义许多不同的函数

reduce
只是
fold
的一个子集

褶皱的定义:

let rec fold f v xs =
    match xs with 
    | [] -> v
    | (x::xs) -> f (x) (fold f v xs )
根据折叠定义的功能示例:

let sum xs = fold (fun x y -> x + y) 0 xs

let product xs = fold (fun x y -> x * y) 1 xs

let length xs = fold (fun _ y -> 1 + y) 0 xs

let all p xs = fold (fun x y -> (p x) && y) true xs

let reverse xs = fold (fun x y -> y @ [x]) [] xs

let map f xs = fold (fun x y -> f x :: y) [] xs

let append xs ys = fold (fun x y -> x :: y) [] [xs;ys]

let any p xs = fold (fun x y -> (p x) || y) false xs 

let filter p xs = 
    let func x y =
        match (p x) with
        | true -> x::y
        | _ -> y
    fold func [] xs

您可以根据彼此编写reduce和fold,例如,
fold f a l
可以写成
reduce f a::l
@Neil-根据
reduce
实现
fold
比这更复杂-fold
的累加器类型不必与列表中的类型相同@为了解释我的错误,我本来打算用另一种方式写它。你定义你的
折叠
列表不同。折叠
列表的类型。折叠
('a->'b->'a)->'a->'b列表->'a
,但是在你的情况下
('a->'b->'b->'b列表->'b
)。我只是想说清楚。另外,您的append实现是错误的。如果向其添加绑定(例如,
List.collect id(fold(fun x y->x::y)[[xs;ys])
,或者用append操作符替换cons,那么它就可以工作。因此,append并不是这个列表中最好的例子。为什么定义reduce会在运行时出错?+1用于说明
fold'的一般性及其表达
reduce'的能力。有些语言有结构手性的概念(Haskell,我在看你),你可以在这个wiki()中直观地向左或向右折叠。对于标识构造,其他两个“基本”FP运算符(过滤器和fmap)也可以通过现有的“折叠”一级语言构造实现(它们都是同构构造)。()见:霍特,普林斯顿(此评论部分太小,无法容纳…)出于好奇。。这是否会使reduce的性能比fold更快,因为它对类型和异常的假设更少?因此,基本上不需要执行
fold
,只需将初始值添加到列表的开头,然后执行
reduce
?那么,
fold
有什么意义呢?@Pacerier-fold的累加器函数有不同的类型:
'state->'a->'state
用于fold,而
'a->'a
用于reduce,因此reduce将结果类型约束为与元素类型相同。见下文。
let sum xs = fold (fun x y -> x + y) 0 xs

let product xs = fold (fun x y -> x * y) 1 xs

let length xs = fold (fun _ y -> 1 + y) 0 xs

let all p xs = fold (fun x y -> (p x) && y) true xs

let reverse xs = fold (fun x y -> y @ [x]) [] xs

let map f xs = fold (fun x y -> f x :: y) [] xs

let append xs ys = fold (fun x y -> x :: y) [] [xs;ys]

let any p xs = fold (fun x y -> (p x) || y) false xs 

let filter p xs = 
    let func x y =
        match (p x) with
        | true -> x::y
        | _ -> y
    fold func [] xs