Trying to learn F# but got confused when trying to distinguish between fold and reduce. Fold seems to do the same thing but takes an extra parameter. Is there a legitimate reason for these two functions to exist or they are there to accommodate people with different backgrounds? (E.g.: String and string in C#)
Here is code snippet copied from sample:
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
takes an explicit initial value for the accumulator whilereduce
uses the first element of the input list as the initial accumulator value.This means the accumulator and therefore result type must match the list element type, whereas they can differ in
fold
as the accumulator is provided separately. This is reflected in the types:In addition
reduce
throws an exception on an empty input list.fold
is a much more valuable function thanreduce
. You can define many different functions in terms offold
.reduce
is just a subset offold
.Definition of fold:
Examples of functions defined in terms of fold:
In addition to what Lee said, you can define
reduce
in terms offold
, but not (easily) the other way round:The fact that
fold
takes an explicit initial value for the accumulator also means that the result of thefold
function can have a different type than the type of values in the list. For example, you can use accumulator of typestring
to concatenate all numbers in a list into a textual representation:When using
reduce
, the type of accumulator is the same as the type of values in the list - this means that if you have a list of numbers, the result will have to be a number. To implement the previous sample, you'd have to convert the numbers tostring
first and then accumulate:Let's look at their signatures:
There are some important differences:
reduce
works on one type of elements only, the accumulator and list elements infold
could be in different types.With
reduce
, you apply a functionf
to every list element starting from the first one:f (... (f i0 i1) i2 ...) iN
.With
fold
, you applyf
starting from the accumulators
:f (... (f s i0) i1 ...) iN
.Therefore,
reduce
results in anArgumentException
on empty list. Moreover,fold
is more generic thanreduce
; you can usefold
to implementreduce
easily.In some cases, using
reduce
is more succinct:or more convenient if there's not any reasonable accumulator:
In general,
fold
is more powerful with an accumulator of an arbitrary type: