Extensions are what you probably expect: helper functions for existing types.
They are defined as modules with the same name as the types they operate on
under the FSharpPlus namespace, so can be accessed via:
open FSharpPlus
Some functions are common across foldable types such as intercalate
on
List, Array and Seq, and others are common across wrapping containers,
such as map
, bind
and apply
on List, Array, and Seq, but also Option and Result.
The singleton
function is already defined for Seq, Array and List, but F#+ adds it for Enumerator:
- Enumerator.singleton - construct a container with the given value inside it
To construct MonadError instances (Result or Choice) you can use result/throw:
- Result.result / Choice.result - construct with the given value (as Ok or Choice1Of2)
- Result.throw / Choice.throw - construct an error from the given value (as Error or Choice2of2)
It's also possible to construct by wrapping exception producing functions:
- Option.protect - returns None on exception
- Result.protect - returns Error with exception value on exception
- Choice.protect - returns Choice2Of2 with exception value on exception
// throws "ArgumentException: The input sequence was empty."
let expectedSingleItem1 : int = List.exactlyOne []
// returns a Result.Error holding the exception as its value:
let expectedSingleItem2 : Result<int,exn> = Result.protect List.exactlyOne []
// ...or like typical try prefixed functions, treat exception as None
let expectedSingleItem3 : Option<int> = Option.protect List.exactlyOne []
// which might look like this:
let inline tryExactlyOne xs = Option.protect List.exactlyOne xs
Some extensions on Result are designed to behave like Option:
- Result.get - unwraps the value when it is an 'ok, otherwise throws an exception
- Result.defaultValue - return the 'ok value if present, otherwise the default value
-
Result.defaultWith - return the 'ok value if present, otherwise apply the given function
to the 'error value
To deconstruct MonadError instances (Result or Choice) use:
- Result.either - unwraps the result by applying the given
ok
or err
function as appropriate
- Choice.either - unwraps the choice by applying the given
choice1
or choice2
function as appropriate
Note that there is also the generic either
operator function that works
exactly the same as Result.either
.
Also, see the generic function option
that
unwraps an Option in a similar way to either
.
Foldables are the class of data structures that can be folded to a summary value.
Most collections, or specifically 'foldable' instances implement these:
- intersperse - takes an element and `intersperses' that element between the elements
let a = ["Bob"; "Jane"] |> List.intersperse "and"
// vat a : string list = ["Bob"; "and"; "Jane"]
let b = "WooHoo" |> String.intersperse '-'
// val b : string = "W-o-o-H-o-o"
- intercalate - insert a list of elements between each element and flattens
let c = [[1;2]; [3;4]] |> List.intercalate [-1;-2];;
// val c : int list = [1; 2; -1; -2; 3; 4]
let d = ["Woo"; "Hoo"] |> String.intercalate "--o.o--";;
// val d : string = "Woo--o.o--Hoo"
- zip/unzip - tuple together values inside two containers, or untuble tupled values
Types that implement these will (typically) have these functions defined:
- map - apply a mapping function to the value inside a container
- bind - take a contained value, and apply a function that produces another contained value
- apply - like map but where the mapping function is also inside a container
These can also be invoked from the generic functions without module prefix as per
generic functions & operators.
Flatten can be used when a container has another container inside it:
- Choice.flatten
- Result.flatten
- Option.flatten (already defined in FSharp Core)
Note that on traversable types like List, Array and Seq, FSharp Core uses the
more common concat
for flatten and so this naming is continued for Enumerable:
Partitioning can be done by applying a separating function that produces a Choice:
- Array.partitionMap
- List.partitionMap
let isEven x = (x % 2) = 0
let chooseEven x = if isEven x then Choice1Of2 x else Choice2Of2 x
let e = [1; 2; 3; 4] |> List.partitionMap chooseEven
// val e : int list * int list = ([2; 4], [1; 3])
F#+ adds functions to convert between Result, Choice and Option types.
These should be self explanatory, but be aware that sometimes they are 'lossy'
usually when converting to Option:
// Convert a Result
to an Option
- effectively throws away error value
// when present, by replacing with None
request |> validateRequest |> Option.ofResult
|
Going the other way is similar, but a value needs to be filled in for None:
let xs = ["some value"]
let firstElementOption = xs |> List.tryHead
// Convert an `Option` to a `Result` will use unit as the Error:
firstElementOption |> Option.toResult
// ...but you can specify an error value with Option.toResultWith:
firstElementOption |> Option.toResultWith "No Element"
Converting between Choice
and Result
is often useful:
let asyncChoice = anAsyncValue |> Async.Catch |> Async.map Result.ofChoice
|
-
String
- intercalate, intersperse,
- split, replace
- isSubString, startsWith, endsWith, contains
- toUpper, toLower
- trimWhiteSpaces
- normalize
- removeDiacritics
- padLeft, padLeftWith, padRight, padRightWith
- trim, trimStart, trimEnd
- item, tryItem
- rev
- take, skip takeWhile, skipWhile
- truncate, drop
- findIndex, tryFindIndex
- findSliceIndex, tryFindSliceIndex
- toArray, ofArray, toList, ofList, toSeq, ofSeq, toCodePoints, ofCodePoints
- getBytes
-
Array
- intercalate, intersperse,
- split, replace,
- findSliceIndex, trySliceIndex,
- partitionMap
-
IList
-
List
- singleton,
- cons,
- apply,
- tails, take, skip, drop,
- intercalate, intersperse,
- split, replace,
- toIReadOnlyList,
- findSliceIndex, tryFindSliceIndex,
- partitionMap
- setAt, removeAt
-
Enumerator
-
EmptyEnumerator
- Empty - create an empty enumerator
-
ConcatEnumerator
-
MapEnumerators
- map, mapi, map2, mapi2, map3
- singleton
- tryItem, nth
- choose
- filter
- unfold
- upto
- zip, zip3
-
Seq
- bind, apply, foldback
- chunkBy
- intersperse, intercalate,
- split, replace
- drop
- replicate
- toIReadOnlyList
- findSliceIndex, tryFindSliceIndex
-
IReadOnlyCollection
- ofArray, ofList, ofSeq
- map
-
IReadOnlyList
- ofArray, toArray
- trySetItem, tryItem
-
Map
- keys, values
- mapValues, mapValues2
- zip, unzip
- unionWith, union, intersectWith, intersect
-
Dict
- toIReadOnlyDictionary
- tryGetValue
- containsKey
- keys, values
- map, map2
- zip, unzip
- unionWith, union, intersectWith, intersect
-
IReadOnlyDictionary
- add,
- tryGetValue, containsKey,
- keys, values,
- map, map2,
- zip, unzip,
- unionWith, union, intersectWith, intersect
-
Option
- apply,
- unzip, zip,
- toResult, toResultWith, ofResult,
- protect
-
Choice
- result, throw - construct a Choice
- bind, apply, flatten,
- map,
- catch, - deprecated
- bindChoice2Of2,
- either,
- protect
-
Result
- result, throw - construct a Result
- apply, (map, bind already defined)
- flatten,
- bindError,
- either,
- protect,
- get,
- defaultValue, defaultWith,
- toChoice, ofChoice,
- partition
These are usable from C#
-
Extension Methods
- IEnumerable<'T'>.GetSlice
- List<'T>.GetSlice
- Task<'T>.WhenAll
- Async.Sequence - of seq, list or array
- Option.Sequence - of seq
namespace FSharpPlus
val expectedSingleItem1: int
Multiple items
val int: value: 'T -> int (requires member op_Explicit)
<summary>Converts the argument to signed 32-bit integer. This is a direct conversion for all
primitive numeric types. For strings, the input is converted using <c>Int32.Parse()</c>
with InvariantCulture settings. Otherwise the operation requires an appropriate
static conversion method on the input type.</summary>
<param name="value">The input value.</param>
<returns>The converted int</returns>
<example id="int-example"><code lang="fsharp"></code></example>
--------------------
[<Struct>]
type int = int32
<summary>An abbreviation for the CLI type <see cref="T:System.Int32" />.</summary>
<category>Basic Types</category>
--------------------
type int<'Measure> =
int
<summary>The type of 32-bit signed integer numbers, annotated with a unit of measure. The unit
of measure is erased in compiled code and when values of this type
are analyzed using reflection. The type is representationally equivalent to
<see cref="T:System.Int32" />.</summary>
<category>Basic Types with Units of Measure</category>
Multiple items
module List
from FSharpPlus
<summary>
Additional operations on List
</summary>
--------------------
module List
from Microsoft.FSharp.Collections
<summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Collections.list`1" />.</summary>
<namespacedoc><summary>Operations for collections such as lists, arrays, sets, maps and sequences. See also
<a href="https://docs.microsoft.com/dotnet/fsharp/language-reference/fsharp-collection-types">F# Collection Types</a> in the F# Language Guide.
</summary></namespacedoc>
--------------------
type List<'T> =
| op_Nil
| op_ColonColon of Head: 'T * Tail: 'T list
interface IReadOnlyList<'T>
interface IReadOnlyCollection<'T>
interface IEnumerable
interface IEnumerable<'T>
member GetReverseIndex: rank: int * offset: int -> int
member GetSlice: startIndex: int option * endIndex: int option -> 'T list
static member Cons: head: 'T * tail: 'T list -> 'T list
member Head: 'T
member IsEmpty: bool
member Item: index: int -> 'T with get
...
<summary>The type of immutable singly-linked lists.</summary>
<remarks>Use the constructors <c>[]</c> and <c>::</c> (infix) to create values of this type, or
the notation <c>[1;2;3]</c>. Use the values in the <c>List</c> module to manipulate
values of this type, or pattern match against the values directly.
</remarks>
<exclude />
val exactlyOne: list: 'T list -> 'T
<summary>Returns the only element of the list.</summary>
<param name="list">The input list.</param>
<returns>The only element of the list.</returns>
<exception cref="T:System.ArgumentException">Thrown when the input does not have precisely one element.</exception>
<example id="exactlyOne-1"><code lang="fsharp">
["the chosen one"] |> List.exactlyOne // evaluates "the chosen one"
</code></example>
<example id="exactlyOne-2"><code lang="fsharp">
let input : string list = []
input |> List.exactlyOne
</code>
Will throw the exception: <c>System.ArgumentException: The input sequence was empty</c></example>
<example id="exactlyOne-3"><code lang="fsharp">
[1..5] |> List.exactlyOne
</code>
Will throw the exception: <c>System.ArgumentException: The input sequence contains more than one element</c></example>
val expectedSingleItem2: Result<int,exn>
Multiple items
module Result
from FSharpPlus
<summary>
Additional operations on Result<'T,'Error>
</summary>
--------------------
module Result
from Microsoft.FSharp.Core
<summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Core.FSharpResult`2" />.</summary>
<category>Choices and Results</category>
--------------------
[<Struct>]
type Result<'T,'TError> =
| Ok of ResultValue: 'T
| Error of ErrorValue: 'TError
<summary>Helper type for error handling without exceptions.</summary>
<category>Choices and Results</category>
type exn = System.Exception
<summary>An abbreviation for the CLI type <see cref="T:System.Exception" />.</summary>
<category>Basic Types</category>
val protect: f: ('T -> 'U) -> x: 'T -> Result<'U,exn>
<summary>
Creates a safe version of the supplied function, which returns a Result<'U,exn> instead of throwing exceptions.
</summary>
val expectedSingleItem3: Option<int>
Multiple items
module Option
from FSharpPlus
<summary>
Additional operations on Option
</summary>
--------------------
module Option
from Microsoft.FSharp.Core
<summary>Contains operations for working with options.</summary>
<category>Options</category>
val protect: f: ('T -> 'U) -> x: 'T -> 'U option
<summary>
Creates a safe version of the supplied function, which returns an option<'U> instead of throwing exceptions.
</summary>
val tryExactlyOne: xs: 'a list -> 'a option
val xs: 'a list
val a: string list
val intersperse: element: 'T -> source: 'T list -> 'T list
<summary>
Inserts a separator element between each element in the source list.
</summary>
val b: string
Multiple items
module String
from FSharpPlus
<summary>
Additional operations on String
</summary>
--------------------
module String
from Microsoft.FSharp.Core
<summary>Functional programming operators for string processing. Further string operations
are available via the member functions on strings and other functionality in
<a href="http://msdn2.microsoft.com/en-us/library/system.string.aspx">System.String</a>
and <a href="http://msdn2.microsoft.com/library/system.text.regularexpressions.aspx">System.Text.RegularExpressions</a> types.
</summary>
<category>Strings and Text</category>
val intersperse: element: char -> source: string -> string
<summary>
Inserts a separator char between each char in the source string.
</summary>
val c: int list
val intercalate: separator: 'a list -> source: seq<'a list> -> 'a list
<summary>
Concatenates all elements, using the specified separator between each element.
</summary>
val d: string
val intercalate: separator: string -> source: seq<string> -> string
<summary>
Concatenates all elements, using the specified separator between each element.
</summary>
val isEven: x: int -> bool
val x: int
val chooseEven: x: int -> Choice<int,int>
union case Choice.Choice1Of2: 'T1 -> Choice<'T1,'T2>
<summary>Choice 1 of 2 choices</summary>
union case Choice.Choice2Of2: 'T2 -> Choice<'T1,'T2>
<summary>Choice 2 of 2 choices</summary>
val e: int list * int list
val partitionMap: mapping: ('T -> Choice<'T1,'T2>) -> source: 'T list -> 'T1 list * 'T2 list
<summary>
Creates two lists by applying the mapping function to each element in the list
and classifying the transformed values depending on whether they were wrapped with Choice1Of2 or Choice2Of2.
</summary>
<returns>
A tuple with both resulting lists.
</returns>
val xs: string list
val firstElementOption: string option
val tryHead: list: 'T list -> 'T option
<summary>Returns the first element of the list, or
<c>None</c> if the list is empty.</summary>
<param name="list">The input list.</param>
<returns>The first element of the list or None.</returns>
<example id="try-head-1"><code lang="fsharp">
let inputs = [ "banana"; "pear" ]
inputs |> List.tryHead
</code>
Evaluates to <c>Some "banana"</c></example>
<example id="try-head-2"><code lang="fsharp">
let inputs : int list = []
inputs |> List.tryHead
</code>
Evaluates to <c>None</c></example>
val toResult: source: 'T option -> Result<'T,unit>
<summary>Converts an option to a Result.</summary>
<param name="source">The option value.</param>
<returns>The resulting Result value.</returns>
val toResultWith: errorValue: 'Error -> source: 'T option -> Result<'T,'Error>
<summary>Converts an option to a Result.</summary>
<param name="errorValue">The error value to be used in case of None.</param>
<param name="source">The option value.</param>
<returns>The resulting Result value.</returns>