open FSharpPlus
You may run this script step-by-step
The order of execution has to be respected since there are redefinitions of functions and operators
The intuitive definition is that a Functor is something you can map over.
So they all have a map
operation which is their minimal definition.
Most containers are functors
let r01 = List.map (fun x -> string (x + 10)) [ 1;2;3 ]
let r02 = Array.map (fun x -> string (x + 10)) [|1;2;3|]
let r03 = Option.map (fun x -> string (x + 10)) (Some 5)
You can think of the Option functor as a particular case of a List that can be either empty or with just 1 element.
We could have used the generic function map
from this library which works on any functor.
let r01' = map (fun x -> string (x + 10)) [ 1;2;3 ]
let r02' = map (fun x -> string (x + 10)) [|1;2;3|]
let r03' = map (fun x -> string (x + 10)) (Some 5)
Now let's define a simple type and make it a functor by adding a Map
static method
type Id<'t> = Id of 't with
static member Map (Id x, f) = Id (f x)
let r04 = map (fun x -> string (x + 10)) (Id 5)
Most computations are also functors
Here's an example with Async functions
let async5 = async.Return 5
let r05 = map (fun x -> string (x + 10)) async5
let r05' = Async.RunSynchronously r05
But even plain functions are functors
let r06 = map (fun x -> string (x + 10)) ((+) 2)
let r06' = r06 3
For functions map
is equivalent to (<<)
this means that mapping over a function is the same as composing the functions with the mapper
A List functor can be thought of as a function which takes an integer index to return a value: f: Naturals -> 't
So, you can think of map
on a List functor as composing a function:
*
let listFunc = function 0 -> 1 | 1 -> 2 | 2 -> 3 // [1;2;3]
let r01'' = map (fun x -> string (x + 10)) listFunc
What about tuples?
*
module TupleFst = let map f (a,b) = (f a, b)
module TupleSnd = let map f (a,b) = (a, f b)
let r07 = TupleFst.map (fun x -> string (x + 10)) (5, "something else")
let r08 = TupleSnd.map (fun x -> string (x + 10)) ("something else", 5)
So there is more than one way to define a functor with tuples.
The same applies to the Discriminated Union of 2 types.
// DUs
module ChoiceFst = let map f = function Choice1Of2 x -> Choice1Of2 (f x) | Choice2Of2 x -> Choice2Of2 x
module ChoiceSnd = let map f = function Choice2Of2 x -> Choice2Of2 (f x) | Choice1Of2 x -> Choice1Of2 x
let choiceValue1:Choice<int,string> = Choice1Of2 5
let choiceValue2:Choice<int,string> = Choice2Of2 "Can't divide by zero."
let r09 = ChoiceFst.map (fun x -> string (x + 10)) choiceValue1
let r09' = ChoiceFst.map (fun x -> string (x + 10)) choiceValue2
let r10 = ChoiceSnd.map (fun x -> "The error was: " + x) choiceValue1
let r10' = ChoiceSnd.map (fun x -> "The error was: " + x) choiceValue2
Tree as a functor
type Tree<'a> =
| Tree of 'a * Tree<'a> * Tree<'a>
| Leaf of 'a
module Tree = let rec map f = function
| Leaf x -> Leaf (f x)
| Tree(x,t1,t2) -> Tree(f x, map f t1, map f t2)
let myTree = Tree(6, Tree(2, Leaf 1, Leaf 3), Leaf 9)
let r11 = Tree.map (fun x -> string (x + 10)) myTree
Q: is String a Functor?
let r12 = String.map (fun c -> System.Char.ToUpper(c)) "Hello world"
A: Kind of, but we can't change the wrapped type. We're stick to ('a->'a) -> C<'a> -> C<'a>
if we assume 'a = char and C<'a> = String
Finally there are some laws:
map id = id
map (f >> g) = map f >> map g
Limitations:
We can define map2
then map3
then .. mapN
?
type Option<'T> with
static member map2 f x y =
match x, y with
| Some x, Some y -> Some (f x y)
| _ -> None
static member map3 f x y z =
match x, y, z with
| Some x, Some y, Some z -> Some (f x y z)
| _ -> None
let r13 = Option.map2 (+) (Some 2) (Some 3)
let r14 = List.map2 (+) [1;2;3] [10;11;12]
let add3 a b c = a + b + c
let r15 = Option.map3 add3 (Some 2) (Some 2) (Some 1)
Question: Is it possible to generalize to mapN?
What if we split map
in 2 steps?
// map ('a -> 'b) -> C<'a> -> C<'b>
// \--------/ \---/ \---/
// (a) (b) (c)
//
// 1) ('a -> 'b) -> C<'a -> 'b>
// \--------/ \---------/
// (a)
//
// 2) C<'a -> 'b> -> C<'a> -> C<'b>
// \---------/ \---/ \---/
// (b) (c)
//
//
// step1 ('a -> 'b) -> "C<'a -> 'b>" Put the function into a context C
// step2 "C<'a -> 'b>" C<'a> -> C<'b> Apply the function in a context C to a value in a context C
Here's an example with Options
let step1 f = Some f
let step2 a b =
match a, b with
| Some f, Some x -> Some (f x)
| _ -> None
let r16 = step1 (fun x -> string (x + 10))
let r17 = step2 r16 (Some 5)
So now instead of writing:
let r18 = Option.map (fun x -> string (x + 10)) (Some 5)
we write
let r18' = step2 (step1 (fun x -> string (x + 10))) (Some 5)
and instead of map2
like this:
let r19 = Option.map2 (+) (Some 2) (Some 3)
we write
let r19i = step2 (step1 (+)) (Some 2)
.. and finally
let r19' = step2 r19i (Some 3)
by applying step2
again. We can apply step2
again if the result is still a function in a container, just like partial application.
lets give names to step1
and step2
: pure
and <*>
module OptionAsApplicative =
let pure' x = Some x
let (<*>) a b =
match a, b with
| Some f, Some x -> Some (f x)
| _ -> None
open OptionAsApplicative
let r18'' = Option.map (fun x -> string (x + 10)) (Some 5)
let r18''' = Some (fun x -> string (x + 10)) <*> Some 5
// analog to:
let r18'''' = (fun x -> string (x + 10)) 5
Now with map3
(and further with mapN)
let r20 = Option.map3 add3 (Some 2) (Some 2) (Some 1)
let r20' = Some add3 <*> Some 2 <*> Some 2 <*> Some 1
// analog to:
let r20'' = add3 2 2 1
but even without add3
we can write 1 + 2 + 2
which is 1 + (2 + 2)
and the same as:
let r20''' = (+) 1 ((+) 2 2)
with options becomes:
let r20'''' = Some (+) <*> Some 1 <*> (Some (+) <*> Some 2 <*> Some 2)
constrast it with
let r20''''' = (+) 1 ( (+) 2 2)
we know apply
is (<|)
in F#
let r21 = (+) <| 1 <| ( (+) <| 2 <| 2)
let r21' = Some (+) <*> Some 1 <*> (Some (+) <*> Some 2 <*> Some 2)
So at this point the name "Applicative Functor" should make sense
Q: Isn't it easier to do just Some ( (+) 1 ((+) 2 2) )
?
We get the same result in the end.
A: Yes, in this particular case it's the same but what if instead of Some 1
we have None
let r22 = Some (+) <*> None <*> (Some (+) <*> Some 2 <*> Some 2)
That's because we're applying functions inside a context.
It looks the same as applying outside but in fact some effects occurs behind the scenes.
To have a better idea let's move out of Option:
[<AutoOpen>]
module Async =
let pure' x = async.Return x
let (<*>) f x = async.Bind(f, fun x1 -> async.Bind(x, fun x2 -> pure'(x1 x2)))
let r23 = async {return (+)} <*> async {return 2} <*> async {return 3}
let r23' = pure' (+) <*> pure' 2 <*> pure' 3
try Async.RunSynchronously r23'
let getLine = async {
let x = System.Console.ReadLine()
return System.Int32.Parse x
}
let r24 = pure' (+) <*> getLine <*> getLine
try Async.RunSynchronously r24
module ListAsApplicative =
let pure' x = [x]
let (<*>) f x = List.collect (fun x1 -> List.collect (fun x2 -> [x1 x2]) x) f
(* here are two other possible implementations of (<*>) for List
let (<*>) f x = f |> List.map (fun f -> x |> List.map (fun x -> f x)) |> List.concat
let (<*>) f x=
seq {
for f in f do
for x in x do
yield f x} |> Seq.toList *)
open ListAsApplicative
let r25 = List.map (fun x -> string (x + 10)) [1;2;3]
let r25' = [fun x -> string (x + 10)] <*> [1..3]
let r25'' = pure' (fun x -> string (x + 10)) <*> [1..3]
let r26 = [string; fun x -> string (x + 10)] <*> [1;2;3]
So, for lists map2
is equivalent to write:
let r27 = [(+)] <*> [1;2] <*> [10;20;30]
let r28 = [(+);(-)] <*> [1;2] <*> [10;20;30]
module SeqAsApplicative =
let pure' x = Seq.initInfinite (fun _ -> x)
let (<*>) f x = Seq.zip f x |> Seq.map (fun (f,x) -> f x)
open SeqAsApplicative
let r29 = Seq.map (fun x -> string (x + 10)) (seq [1;2;3]) |> Seq.toList
let r29' = pure' (fun x -> string (x + 10)) <*> seq [1;2;3] |> Seq.toList
let r30 = seq [(+);(-)] <*> seq [1;2] <*> seq [10;20;30] |> Seq.toList // compare it with r28
An exotic case where there is no pure
.
module MapAsApplicative =
let (<*>) (f:Map<'k,_>) x =
Map (seq {
for KeyValue(k, vf) in f do
match Map.tryFind k x with
| Some vx -> yield k, vf vx
| _ -> () })
open MapAsApplicative
let r31 = Map ['a',(+);'b',(-)] <*> Map ['a',1;'b',2] <*> Map ['a',10;'b',20;'c',30]
let r32 = Map ['c',(+);'b',(-)] <*> Map ['a',1;'b',2] <*> Map ['a',10;'b',20;'c',30]
open OptionAsApplicative
let a = Some 3
let b = Some 2
let c = Some 1
let half x = x / 2
let f a b c =
let x = a + b
let y = half c
x + y
let f' a b c =
let x = Some (+) <*> a <*> b
let y = Some half <*> c
Some (+) <*> x <*> y
let r33 = f' (Some 1) (Some 2) (Some 3)
let r33' = f' None (Some 2) (Some 3)
OK, but if I want to use a function like:
let exactHalf x =
if x % 2 = 0 then Some (x / 2)
else None
It doesn't fit
// let f'' a b c =
// let x = Some (+) <*> a <*> b
// let y = Some exactHalf <*> c // y will be inferred as option<option<int>>
// Some (+) <*> x <*> y // so this will not compile
The problem is, we were working with ordinary functions.
When we lift these function into C, we get functions wrapped in contexts.
With Applicatives we can use either a function in a context which is ready to use or an ordinary function, which we can lift easily with pure
.
But exactHalf
is a different thing: its signature is int -> Option<int>
.
This function goes from a pure value to a value in a context, so either:
1) we use it directly but we first need to extract the argument from the context.
2) we use it in an Applicative, we will get a value in a context in another context, so we will need to flatten both contexts.
Monad provides solutions to both alternatives
// bind : C<'a> -> ('a->C<'b>) -> C<'b>
// join : C<C<'a>> -> C<'a>
module OptionAsMonad =
let join x = Option.bind id x
let (>>=) x f = Option.bind f x
// in monads pure' is called return, unit or result, but it's essentially the same function.
let return' x = Some x
open OptionAsMonad
let f'' a b c =
let x = Some (+) <*> a <*> b
let y = Some exactHalf <*> c |> join
Some (+) <*> x <*> y
let f''' a b c =
let x = Some (+) <*> a <*> b
let y = c >>= exactHalf
Some (+) <*> x <*> y
All monads are automatically applicatives, remember <*>
for lists, it was:
let (<*>) f x = List.collect (fun x1 -> List.collect (fun x2 -> [x1 x2]) x) f
But List.collect
is in fact bind
, and [x1 x2]
is pure (x1 x2)
// let (<*>) f x = f >>= (fun x1 -> x >>= (fun x2 -> pure' (x1 x2)))
And this definition of <*>
applies to all monads.
Q: but we said all applicatives are functors, so monads should be functors as well, right?
A: Yes, they are, and this is the general definition of map
based on bind
and result
(aka return or pure)
let map f x = x >>= (pure' << f)
Recommended links
Same explanation but with pictures
http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
Haskell typeclasses
http://www.haskell.org/haskellwiki/Typeclassopedia
namespace FSharpPlus
val r01: string list
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 map: mapping: ('T -> 'U) -> list: 'T list -> 'U list
<summary>Builds a new collection whose elements are the results of applying the given function
to each of the elements of the collection.</summary>
<param name="mapping">The function to transform elements from the input list.</param>
<param name="list">The input list.</param>
<returns>The list of transformed elements.</returns>
<example id="map-1"><code lang="fsharp">
let inputs = [ "a"; "bbb"; "cc" ]
inputs |> List.map (fun x -> x.Length)
</code>
Evaluates to <c>[ 1; 3; 2 ]</c></example>
val x: int
Multiple items
val string: value: 'T -> string
<summary>Converts the argument to a string using <c>ToString</c>.</summary>
<remarks>For standard integer and floating point values the and any type that implements <c>IFormattable</c><c>ToString</c> conversion uses <c>CultureInfo.InvariantCulture</c>. </remarks>
<param name="value">The input value.</param>
<returns>The converted string.</returns>
<example id="string-example"><code lang="fsharp"></code></example>
--------------------
type string = System.String
<summary>An abbreviation for the CLI type <see cref="T:System.String" />.</summary>
<category>Basic Types</category>
val r02: string[]
Multiple items
module Array
from FSharpPlus
<summary>
Additional operations on Array
</summary>
--------------------
module Array
from Microsoft.FSharp.Collections
<summary>Contains operations for working with arrays.</summary>
<remarks>
See also <a href="https://docs.microsoft.com/dotnet/fsharp/language-reference/arrays">F# Language Guide - Arrays</a>.
</remarks>
val map: mapping: ('T -> 'U) -> array: 'T[] -> 'U[]
<summary>Builds a new array whose elements are the results of applying the given function
to each of the elements of the array.</summary>
<param name="mapping">The function to transform elements of the array.</param>
<param name="array">The input array.</param>
<returns>The array of transformed elements.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when the input array is null.</exception>
<example id="map-1"><code lang="fsharp">
let inputs = [| "a"; "bbb"; "cc" |]
inputs |> Array.map (fun x -> x.Length)
</code>
Evaluates to <c>[| 1; 3; 2 |]</c></example>
val r03: string option
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 map: mapping: ('T -> 'U) -> option: 'T option -> 'U option
<summary><c>map f inp</c> evaluates to <c>match inp with None -> None | Some x -> Some (f x)</c>.</summary>
<param name="mapping">A function to apply to the option value.</param>
<param name="option">The input option.</param>
<returns>An option of the input value after applying the mapping function, or None if the input is None.</returns>
<example id="map-1"><code lang="fsharp">
None |> Option.map (fun x -> x * 2) // evaluates to None
Some 42 |> Option.map (fun x -> x * 2) // evaluates to Some 84
</code></example>
union case Option.Some: Value: 'T -> Option<'T>
<summary>The representation of "Value of type 'T"</summary>
<param name="Value">The input value.</param>
<returns>An option representing the value.</returns>
val r01': string list
val map: f: ('T -> 'U) -> x: 'Functor<'T> -> 'Functor<'U> (requires member Map)
<summary>Lifts a function into a Functor.</summary>
<category index="1">Functor</category>
val r02': string[]
val r03': string option
Multiple items
union case Id.Id: 't -> Id<'t>
--------------------
type Id<'t> =
| Id of 't
static member Map: Id<'a> * f: ('a -> 'b) -> Id<'b>
Multiple items
module Map
from FSharpPlus
<summary>
Additional operations on Map<'Key, 'Value>
</summary>
--------------------
module Map
from Microsoft.FSharp.Collections
<summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Collections.FSharpMap`2" />.</summary>
--------------------
type Map<'Key,'Value (requires comparison)> =
interface IReadOnlyDictionary<'Key,'Value>
interface IReadOnlyCollection<KeyValuePair<'Key,'Value>>
interface IEnumerable
interface IComparable
interface IEnumerable<KeyValuePair<'Key,'Value>>
interface ICollection<KeyValuePair<'Key,'Value>>
interface IDictionary<'Key,'Value>
new: elements: seq<'Key * 'Value> -> Map<'Key,'Value>
member Add: key: 'Key * value: 'Value -> Map<'Key,'Value>
member Change: key: 'Key * f: ('Value option -> 'Value option) -> Map<'Key,'Value>
...
<summary>Immutable maps based on binary trees, where keys are ordered by F# generic comparison. By default
comparison is the F# structural comparison function or uses implementations of the IComparable interface on key values.</summary>
<remarks>See the <see cref="T:Microsoft.FSharp.Collections.MapModule" /> module for further operations on maps.
All members of this class are thread-safe and may be used concurrently from multiple threads.</remarks>
--------------------
new: elements: seq<'Key * 'Value> -> Map<'Key,'Value>
val x: 'a
val f: ('a -> 'b)
val r04: Id<string>
val async5: Async<int>
val async: AsyncBuilder
<summary>Builds an asynchronous workflow using computation expression syntax.</summary>
<example id="async-1"><code lang="fsharp">
let sleepExample() =
async {
printfn "sleeping"
do! Async.Sleep 10
printfn "waking up"
return 6
}
sleepExample() |> Async.RunSynchronously
</code></example>
member AsyncBuilder.Return: value: 'T -> Async<'T>
val r05: Async<string>
val r05': string
Multiple items
module Async
from FSharpPlus
<summary>
Additional operations on Async
</summary>
--------------------
type Async =
static member AsBeginEnd: computation: ('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent: event: IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult: iar: IAsyncResult * ?millisecondsTimeout: int -> Async<bool>
static member AwaitTask: task: Task<'T> -> Async<'T> + 1 overload
static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout: int -> Async<bool>
static member CancelDefaultToken: unit -> unit
static member Catch: computation: Async<'T> -> Async<Choice<'T,exn>>
static member Choice: computations: seq<Async<'T option>> -> Async<'T option>
static member FromBeginEnd: beginAction: (AsyncCallback * obj -> IAsyncResult) * endAction: (IAsyncResult -> 'T) * ?cancelAction: (unit -> unit) -> Async<'T> + 3 overloads
static member FromContinuations: callback: (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
...
<summary>Holds static members for creating and manipulating asynchronous computations.</summary>
<remarks>
See also <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">F# Language Guide - Async Workflows</a>.
</remarks>
<category index="1">Async Programming</category>
--------------------
type Async<'T>
<summary>
An asynchronous computation, which, when run, will eventually produce a value of type T, or else raises an exception.
</summary>
<remarks>
This type has no members. Asynchronous computations are normally specified either by using an async expression
or the static methods in the <see cref="T:Microsoft.FSharp.Control.FSharpAsync`1" /> type.
See also <a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">F# Language Guide - Async Workflows</a>.
</remarks>
<namespacedoc><summary>
Library functionality for asynchronous programming, events and agents. See also
<a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/asynchronous-workflows">Asynchronous Programming</a>,
<a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/members/events">Events</a> and
<a href="https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/lazy-expressions">Lazy Expressions</a> in the
F# Language Guide.
</summary></namespacedoc>
<category index="1">Async Programming</category>
static member Async.RunSynchronously: computation: Async<'T> * ?timeout: int * ?cancellationToken: System.Threading.CancellationToken -> 'T
val r06: (int -> string)
val r06': string
val listFunc: _arg1: int -> int
val r01'': (int -> string)
val map: f: ('a -> 'b) -> a: 'a * b: 'c -> 'b * 'c
val a: 'a
val b: 'c
val map: f: ('a -> 'b) -> a: 'c * b: 'a -> 'c * 'b
val a: 'c
val b: 'a
val r07: string * string
module TupleFst
from Applicative-functors
val r08: string * string
module TupleSnd
from Applicative-functors
val map: f: ('a -> 'b) -> _arg1: Choice<'a,'c> -> Choice<'b,'c>
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 x: 'c
val map: f: ('a -> 'b) -> _arg1: Choice<'c,'a> -> Choice<'c,'b>
val choiceValue1: Choice<int,string>
Multiple items
module Choice
from FSharpPlus
<summary>
Additional operations on Choice
</summary>
--------------------
type Choice<'T1,'T2> =
| Choice1Of2 of 'T1
| Choice2Of2 of 'T2
<summary>Helper types for active patterns with 2 choices.</summary>
<category index="5">Choices and Results</category>
--------------------
type Choice<'T1,'T2,'T3> =
| Choice1Of3 of 'T1
| Choice2Of3 of 'T2
| Choice3Of3 of 'T3
<summary>Helper types for active patterns with 3 choices.</summary>
<category>Choices and Results</category>
--------------------
type Choice<'T1,'T2,'T3,'T4> =
| Choice1Of4 of 'T1
| Choice2Of4 of 'T2
| Choice3Of4 of 'T3
| Choice4Of4 of 'T4
<summary>Helper types for active patterns with 4 choices.</summary>
<category>Choices and Results</category>
--------------------
type Choice<'T1,'T2,'T3,'T4,'T5> =
| Choice1Of5 of 'T1
| Choice2Of5 of 'T2
| Choice3Of5 of 'T3
| Choice4Of5 of 'T4
| Choice5Of5 of 'T5
<summary>Helper types for active patterns with 5 choices.</summary>
<category>Choices and Results</category>
--------------------
type Choice<'T1,'T2,'T3,'T4,'T5,'T6> =
| Choice1Of6 of 'T1
| Choice2Of6 of 'T2
| Choice3Of6 of 'T3
| Choice4Of6 of 'T4
| Choice5Of6 of 'T5
| Choice6Of6 of 'T6
<summary>Helper types for active patterns with 6 choices.</summary>
<category>Choices and Results</category>
--------------------
type Choice<'T1,'T2,'T3,'T4,'T5,'T6,'T7> =
| Choice1Of7 of 'T1
| Choice2Of7 of 'T2
| Choice3Of7 of 'T3
| Choice4Of7 of 'T4
| Choice5Of7 of 'T5
| Choice6Of7 of 'T6
| Choice7Of7 of 'T7
<summary>Helper types for active patterns with 7 choices.</summary>
<category>Choices and Results</category>
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>
val choiceValue2: Choice<int,string>
val r09: Choice<string,string>
module ChoiceFst
from Applicative-functors
val r09': Choice<string,string>
val r10: Choice<int,string>
module ChoiceSnd
from Applicative-functors
val x: string
val r10': Choice<int,string>
Multiple items
union case Tree.Tree: 'a * Tree<'a> * Tree<'a> -> Tree<'a>
--------------------
type Tree<'a> =
| Tree of 'a * Tree<'a> * Tree<'a>
| Leaf of 'a
union case Tree.Leaf: 'a -> Tree<'a>
type Tree<'a> =
| Tree of 'a * Tree<'a> * Tree<'a>
| Leaf of 'a
val map: f: ('a -> 'b) -> _arg1: Tree<'a> -> Tree<'b>
val t1: Tree<'a>
val t2: Tree<'a>
val myTree: Tree<int>
Multiple items
union case Tree.Tree: 'a * Tree<'a> * Tree<'a> -> Tree<'a>
--------------------
module Tree
from Applicative-functors
--------------------
type Tree<'a> =
| Tree of 'a * Tree<'a> * Tree<'a>
| Leaf of 'a
val r11: Tree<string>
val r12: 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 map: mapping: (char -> char) -> str: string -> string
<summary>Builds a new string whose characters are the results of applying the function <c>mapping</c>
to each of the characters of the input string.</summary>
<param name="mapping">The function to apply to the characters of the string.</param>
<param name="str">The input string.</param>
<returns>The resulting string.</returns>
<example id="map-1"> Changing case to upper for all characters in the input string
<code lang="fsharp">
open System
let input = "Hello there!"
input |> String.map Char.ToUpper // evaluates "HELLO THERE!"
</code></example>
val c: char
namespace System
[<Struct>]
type Char =
member CompareTo: value: char -> int + 1 overload
member Equals: obj: char -> bool + 1 overload
member GetHashCode: unit -> int
member GetTypeCode: unit -> TypeCode
member ToString: unit -> string + 2 overloads
static member ConvertFromUtf32: utf32: int -> string
static member ConvertToUtf32: highSurrogate: char * lowSurrogate: char -> int + 1 overload
static member GetNumericValue: c: char -> float + 1 overload
static member GetUnicodeCategory: c: char -> UnicodeCategory + 1 overload
static member IsAscii: c: char -> bool
...
<summary>Represents a character as a UTF-16 code unit.</summary>
System.Char.ToUpper(c: char) : char
System.Char.ToUpper(c: char, culture: System.Globalization.CultureInfo) : char
val f: ('a -> 'b -> 'c)
val x: 'a option
val y: 'b option
val y: 'b
union case Option.None: Option<'T>
<summary>The representation of "No value"</summary>
val f: ('a -> 'b -> 'c -> 'd)
val z: 'c option
val z: 'c
val r13: int option
Multiple items
val map2: mapping: ('T1 -> 'T2 -> 'U) -> option1: 'T1 option -> option2: 'T2 option -> 'U option
<summary><c>map f option1 option2</c> evaluates to <c>match option1, option2 with Some x, Some y -> Some (f x y) | _ -> None</c>.</summary>
<param name="mapping">A function to apply to the option values.</param>
<param name="option1">The first option.</param>
<param name="option2">The second option.</param>
<returns>An option of the input values after applying the mapping function, or None if either input is None.</returns>
<example id="map2-1"><code lang="fsharp">
(None, None) ||> Option.map2 (fun x y -> x + y) // evaluates to None
(Some 5, None) ||> Option.map2 (fun x y -> x + y) // evaluates to None
(None, Some 10) ||> Option.map2 (fun x y -> x + y) // evaluates to None
(Some 5, Some 10) ||> Option.map2 (fun x y -> x + y) // evaluates to Some 15
</code></example>
--------------------
static member Option.map2: f: ('a -> 'b -> 'c) -> x: 'a option -> y: 'b option -> 'c option
val r14: int list
val map2: mapping: ('T1 -> 'T2 -> 'U) -> list1: 'T1 list -> list2: 'T2 list -> 'U list
<summary>Builds a new collection whose elements are the results of applying the given function
to the corresponding elements of the two collections pairwise.</summary>
<param name="mapping">The function to transform pairs of elements from the input lists.</param>
<param name="list1">The first input list.</param>
<param name="list2">The second input list.</param>
<returns>The list of transformed elements.</returns>
<example id="item-1"><code lang="fsharp">
let inputs1 = ["a"; "bad"; "good"]
let inputs2 = [0; 2; 1]
(inputs1, inputs2) ||> List.map2 (fun x y -> x.[y])
</code>
Evaluates to <c>seq ['a'; 'd'; 'o']</c></example>
val add3: a: int -> b: int -> c: int -> int
val a: int
val b: int
val c: int
val r15: int option
Multiple items
val map3: mapping: ('T1 -> 'T2 -> 'T3 -> 'U) -> option1: 'T1 option -> option2: 'T2 option -> option3: 'T3 option -> 'U option
<summary><c>map f option1 option2 option3</c> evaluates to <c>match option1, option2, option3 with Some x, Some y, Some z -> Some (f x y z) | _ -> None</c>.</summary>
<param name="mapping">A function to apply to the option values.</param>
<param name="option1">The first option.</param>
<param name="option2">The second option.</param>
<param name="option3">The third option.</param>
<returns>An option of the input values after applying the mapping function, or None if any input is None.</returns>
<example id="map3-1"><code lang="fsharp">
(None, None, None) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to None
(Some 100, None, None) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to None
(None, Some 100, None) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to None
(None, None, Some 100) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to None
(Some 5, Some 100, Some 10) |||> Option.map3 (fun x y z -> x + y + z) // evaluates to Some 115
</code></example>
--------------------
static member Option.map3: f: ('a -> 'b -> 'c -> 'd) -> x: 'a option -> y: 'b option -> z: 'c option -> 'd option
val step1: f: 'a -> 'a option
val f: 'a
val step2: a: ('a -> 'b) option -> b: 'a option -> 'b option
val a: ('a -> 'b) option
val b: 'a option
val r16: (int -> string) option
val r17: string option
val r18: string option
val r18': string option
val r19: int option
val r19i: (int -> int) option
val r19': int option
val pure': x: 'a -> 'a option
module OptionAsApplicative
from Applicative-functors
val r18'': string option
val r18''': string option
val r18'''': string
val r20: int option
val r20': int option
val r20'': int
val r20''': int
val r20'''': int option
val r20''''': int
val r21: int
val r21': int option
val r22: int option
Multiple items
type AutoOpenAttribute =
inherit Attribute
new: unit -> AutoOpenAttribute + 1 overload
member Path: string
<summary>Indicates a construct is automatically opened when brought into scope through
an assembly reference or then opening of the containing namespace or module.</summary>
<remarks>When applied to an assembly, this attribute must be given a string
argument, and this indicates a valid module or namespace in that assembly. Source
code files compiled with a reference to this assembly are processed in an environment
where the given path is automatically opened.
When applied to a type or module within an assembly, then the attribute must not be given any arguments, and
the type or module is implicitly opened when its enclosing namespace or module is opened.
</remarks>
<category>Attributes</category>
--------------------
new: unit -> AutoOpenAttribute
new: path: string -> AutoOpenAttribute
val pure': x: 'a -> Async<'a>
val f: Async<('a -> 'b)>
val x: Async<'a>
member AsyncBuilder.Bind: computation: Async<'T> * binder: ('T -> Async<'U>) -> Async<'U>
val x1: ('a -> 'b)
val x2: 'a
val r23: Async<int>
val r23': Async<int>
val getLine: Async<int>
type Console =
static member Beep: unit -> unit + 1 overload
static member Clear: unit -> unit
static member GetCursorPosition: unit -> struct (int * int)
static member MoveBufferArea: sourceLeft: int * sourceTop: int * sourceWidth: int * sourceHeight: int * targetLeft: int * targetTop: int -> unit + 1 overload
static member OpenStandardError: unit -> Stream + 1 overload
static member OpenStandardInput: unit -> Stream + 1 overload
static member OpenStandardOutput: unit -> Stream + 1 overload
static member Read: unit -> int
static member ReadKey: unit -> ConsoleKeyInfo + 1 overload
static member ReadLine: unit -> string
...
<summary>Represents the standard input, output, and error streams for console applications. This class cannot be inherited.</summary>
System.Console.ReadLine() : string
[<Struct>]
type Int32 =
member CompareTo: value: int -> int + 1 overload
member Equals: obj: int -> bool + 1 overload
member GetHashCode: unit -> int
member GetTypeCode: unit -> TypeCode
member ToString: unit -> string + 3 overloads
member TryFormat: destination: Span<char> * charsWritten: byref<int> * ?format: ReadOnlySpan<char> * ?provider: IFormatProvider -> bool
static member Parse: s: ReadOnlySpan<char> * ?style: NumberStyles * ?provider: IFormatProvider -> int + 4 overloads
static member TryParse: s: ReadOnlySpan<char> * style: NumberStyles * provider: IFormatProvider * result: byref<int> -> bool + 3 overloads
static val MaxValue: int
static val MinValue: int
<summary>Represents a 32-bit signed integer.</summary>
System.Int32.Parse(s: string) : int
System.Int32.Parse(s: string, provider: System.IFormatProvider) : int
System.Int32.Parse(s: string, style: System.Globalization.NumberStyles) : int
System.Int32.Parse(s: string, style: System.Globalization.NumberStyles, provider: System.IFormatProvider) : int
System.Int32.Parse(s: System.ReadOnlySpan<char>, ?style: System.Globalization.NumberStyles, ?provider: System.IFormatProvider) : int
val r24: Async<int>
val pure': x: 'a -> 'a list
val f: ('a -> 'b) list
val x: 'a list
val collect: mapping: ('T -> 'U list) -> list: 'T list -> 'U list
<summary>For each element of the list, applies the given function. Concatenates all the results and return the combined list.</summary>
<param name="mapping">The function to transform each input element into a sublist to be concatenated.</param>
<param name="list">The input list.</param>
<returns>The concatenation of the transformed sublists.</returns>
<example id="collect-1"> For each positive number in the array we are generating all the previous positive numbers
<code lang="fsharp">
[1..4] |> List.collect (fun x -> [1..x])
</code>
The sample evaluates to <c>[1; 1; 2; 1; 2; 3; 1; 2; 3; 4]</c> (added extra spaces for easy reading)
</example>
module ListAsApplicative
from Applicative-functors
val r25: string list
val r25': string list
val r25'': string list
val r26: string list
val r27: int list
val r28: int list
val pure': x: 'a -> seq<'a>
Multiple items
module Seq
from FSharpPlus.Operators
--------------------
module Seq
from FSharpPlus
<summary>
Additional operations on Seq
</summary>
--------------------
module Seq
from Microsoft.FSharp.Collections
<summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Collections.seq`1" />.</summary>
val initInfinite: initializer: (int -> 'T) -> seq<'T>
<summary>Generates a new sequence which, when iterated, will return successive
elements by calling the given function. The results of calling the function
will not be saved, that is the function will be reapplied as necessary to
regenerate the elements. The function is passed the index of the item being
generated.</summary>
<remarks>The returned sequence may be passed between threads safely. However,
individual IEnumerator values generated from the returned sequence should not be accessed concurrently.
Iteration can continue up to <c>Int32.MaxValue</c>.</remarks>
<param name="initializer">A function that generates an item in the sequence from a given index.</param>
<returns>The result sequence.</returns>
<example id="init-infinite-1"><code lang="fsharp">
(+) 5 |> Seq.initInfinite
</code>
Evaluates to a sequence yielding the same results as <c>seq { 5; 6; 7; 8; ... }</c></example>
val f: seq<('a -> 'b)>
val x: seq<'a>
val zip: source1: seq<'T1> -> source2: seq<'T2> -> seq<'T1 * 'T2>
<summary>Combines the two sequences into a sequence of pairs. The two sequences need not have equal lengths:
when one sequence is exhausted any remaining elements in the other
sequence are ignored.</summary>
<param name="source1">The first input sequence.</param>
<param name="source2">The second input sequence.</param>
<returns>The result sequence.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when either of the input sequences is null.</exception>
<example id="zip-1"><code lang="fsharp">
let numbers = [1; 2]
let names = ["one"; "two"]
Seq.zip numbers names
</code>
Evaluates to a sequence yielding the same results as <c>seq { (1, "one"); (2, "two") }</c>.
</example>
val map: mapping: ('T -> 'U) -> source: seq<'T> -> seq<'U>
<summary>Builds a new collection whose elements are the results of applying the given function
to each of the elements of the collection. The given function will be applied
as elements are demanded using the <c>MoveNext</c> method on enumerators retrieved from the
object.</summary>
<remarks>The returned sequence may be passed between threads safely. However,
individual IEnumerator values generated from the returned sequence should not be accessed concurrently.</remarks>
<param name="mapping">A function to transform items from the input sequence.</param>
<param name="source">The input sequence.</param>
<returns>The result sequence.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
<example id="item-1"><code lang="fsharp">
let inputs = ["a"; "bbb"; "cc"]
inputs |> Seq.map (fun x -> x.Length)
</code>
Evaluates to a sequence yielding the same results as <c>seq { 1; 3; 2 }</c></example>
module SeqAsApplicative
from Applicative-functors
val r29: string list
Multiple items
val seq: sequence: seq<'T> -> seq<'T>
<summary>Builds a sequence using sequence expression syntax</summary>
<param name="sequence">The input sequence.</param>
<returns>The result sequence.</returns>
<example id="seq-cast-example"><code lang="fsharp">
seq { for i in 0..10 do yield (i, i*i) }
</code></example>
--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>
<summary>An abbreviation for the CLI type <see cref="T:System.Collections.Generic.IEnumerable`1" /></summary>
<remarks>
See the <see cref="T:Microsoft.FSharp.Collections.SeqModule" /> module for further operations related to sequences.
See also <a href="https://docs.microsoft.com/dotnet/fsharp/language-reference/sequences">F# Language Guide - Sequences</a>.
</remarks>
val toList: source: seq<'T> -> 'T list
<summary>Builds a list from the given collection.</summary>
<param name="source">The input sequence.</param>
<returns>The result list.</returns>
<exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
<example id="tolist-1"><code lang="fsharp">
let inputs = seq { 1; 2; 5 }
inputs |> Seq.toList
</code>
Evaluates to <c>[ 1; 2; 5 ]</c>.
</example>
val r29': string list
val r30: int list
val f: Map<'k,('a -> 'b)> (requires comparison)
val x: Map<'k,'a> (requires comparison)
active recognizer KeyValue: System.Collections.Generic.KeyValuePair<'Key,'Value> -> 'Key * 'Value
<summary>An active pattern to match values of type <see cref="T:System.Collections.Generic.KeyValuePair" /></summary>
<param name="keyValuePair">The input key/value pair.</param>
<returns>A tuple containing the key and value.</returns>
<example id="keyvalue-example"><code lang="fsharp"></code></example>
val k: 'k (requires comparison)
val vf: ('a -> 'b)
val tryFind: key: 'Key -> table: Map<'Key,'T> -> 'T option (requires comparison)
<summary>Lookup an element in the map, returning a <c>Some</c> value if the element is in the domain
of the map and <c>None</c> if not.</summary>
<param name="key">The input key.</param>
<param name="table">The input map.</param>
<returns>The found <c>Some</c> value or <c>None</c>.</returns>
<example id="tryfind-1"><code lang="fsharp">
let sample = Map [ (1, "a"); (2, "b") ]
sample |> Map.tryFind 1 // evaluates to Some "a"
sample |> Map.tryFind 3 // evaluates to None
</code></example>
val vx: 'a
module MapAsApplicative
from Applicative-functors
val r31: Map<char,int>
val r32: Map<char,int>
val a: int option
val b: int option
val c: int option
val half: x: int -> int
val f: a: int -> b: int -> c: int -> int
val y: int
val f': a: int option -> b: int option -> c: int option -> int option
val x: int option
val y: int option
val r33: int option
val r33': int option
val exactHalf: x: int -> int option
val join: x: 'a option option -> 'a option
val x: 'a option option
val bind: binder: ('T -> 'U option) -> option: 'T option -> 'U option
<summary><c>bind f inp</c> evaluates to <c>match inp with None -> None | Some x -> f x</c></summary>
<param name="binder">A function that takes the value of type T from an option and transforms it into
an option containing a value of type U.</param>
<param name="option">The input option.</param>
<returns>An option of the output type of the binder.</returns>
<example id="bind-1"><code lang="fsharp">
let tryParse (input: string) =
match System.Int32.TryParse input with
| true, v -> Some v
| false, _ -> None
None |> Option.bind tryParse // evaluates to None
Some "42" |> Option.bind tryParse // evaluates to Some 42
Some "Forty-two" |> Option.bind tryParse // evaluates to None
</code></example>
val id: x: 'T -> 'T
<summary>The identity function</summary>
<param name="x">The input value.</param>
<returns>The same value.</returns>
<example id="id-example"><code lang="fsharp">
id 12 // Evaulates to 12
id "abc" // Evaulates to "abc"
</code></example>
val f: ('a -> 'b option)
val return': x: 'a -> 'a option
module OptionAsMonad
from Applicative-functors
val f'': a: int option -> b: int option -> c: int option -> int option
val f''': a: int option -> b: int option -> c: int option -> int option
val map: f: ('a -> 'b) -> x: 'a option -> 'b option