FSharp.Control.Fold
2.0.0
dotnet add package FSharp.Control.Fold --version 2.0.0
NuGet\Install-Package FSharp.Control.Fold -Version 2.0.0
<PackageReference Include="FSharp.Control.Fold" Version="2.0.0" />
<PackageVersion Include="FSharp.Control.Fold" Version="2.0.0" />
<PackageReference Include="FSharp.Control.Fold" />
paket add FSharp.Control.Fold --version 2.0.0
#r "nuget: FSharp.Control.Fold, 2.0.0"
#:package FSharp.Control.Fold@2.0.0
#addin nuget:?package=FSharp.Control.Fold&version=2.0.0
#tool nuget:?package=FSharp.Control.Fold&version=2.0.0
FSharp.Control.Fold
Using this F# library (NuGet) you define folding of data structures or streams as values of type Fold<'a,'b> and combine smaller folds into larger folds using F# applicative computation expressions.
One benefit of this is that the programmer does not have to define combined folder functions manually, which gets tedious quickly as more folds are to be combined. Instead, combining folds is declarative and can reuse predefined fold values. Another major benefit is that combining explicit folds-as-values guarantees that the resulting Fold<'a,'b> will go through the data structure (or stream) exactly once, folding individual constituent values at the same time and producing a 'b. This is especially important and useful when evaluating, say, seq<'a> is effectful, for example when 'a values are retrieved from a database.
FSharp.Control.Fold is directly based on the Haskell library foldl, although the definition of the main Fold<'a,'b> type is different as one-to-one port is impossible.
Supported foldable types
FSharp.Control.Fold includes support for folding standard F# types seq<'a>, List<'a>, Set<'a>, Map<'k,'v>, Option<'a> and ValueOption<'a>. The naming convention is that the folding function is named foldl ("fold left"). For example, the library provides
Seq.foldl (fold : Fold<'a,'b>) (sequence : seq<'a>) : 'b = ...
and similarly List.foldl, Set.foldl and so on.
Basic usage
- Open namespace
FSharp.Control.Fold - Define your folding computation using function
Fold.makeFold - Apply your fold using function
foldl
Example:
open FSharp.Control.Fold
let length = Fold.makeFold (fun count _ -> count + 1) 0 id
List.foldl length [1;2;3;4]
Function makeFold is the main "constructor" for folds-as-values. Regular fold functions from the FSharp.Core library accept two fold "ingredients": a folder function and initial state. In contrast, makeFold accepts three ingredients: a folder function, initial state and a function which transforms final state to the final result. Therefore, in Fold<'a,'b> type parameter 'a is the type of elements and 'b is the final result, while the type of state gets hidden by makeFold and does not occur in Fold<'a,'b>. This is one of the main points to understand about this library.
Combining folds
Two or more folds can be combined into a single fold in an applicative computation expression. For example, the following expression is a fold which computes the length (count) of the data structure or stream and the sum of its elements (note the type of the final result):
let lengthAndSum : Fold<int, int * int> = fold {
let! length = length // Reuse an existing Fold, see above
and! sum = Fold.makeFold (+) 0 id
return (length, sum)
}
It is of course possible to use more than two folds in a computation expression. Just add more and! bindings.
Making your data types compatible with the library
If you have your own foldable data type, for example Tree<'a>, then you can make it compatible with FSharp.Control.Fold by implementing a foldl function for it by yourself. Just copy one of the definitions from Foldables.fs and adjust it by inserting the "native" Tree.fold function at the self-explanatory place. Do not focus on implementation details; just copy, adjust and place somewhere in your solution. For example:
let foldl (fold : Fold<'a,'b>) (tree : Tree<'a>) : 'b =
fold.Elim { new FoldCont<_,_,_> with
member _.Apply step initial extract = extract (Tree.fold step initial tree)
}
Status of the library
Although there are no tests yet, the library is certainly usable. Future releases will add the following:
- tests
- documentation comments
- more complete API description for module
Foldin this file - predefined folds like in the original foldl library
You can see some examples and benchmarks in (executable) projects Examples and Benchmarks respectively. These will also be extended in the future.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- FSharp.Core (>= 10.1.203)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.