FSharpPlus


Alternative

Applicative Functors which also have a monoid structure. ___

Minimal complete definition

static member Return (x: 'T) : 'Alternative<'T>
static member (<*>) (f: 'T -> 'U, x: 'Alternative<'T>) : 'Alternative<'U>
static member get_Empty () : 'Alternative
static member (<|>) (x: 'Alternative<'T>, y: 'Alternative<'T>) : 'Alternative<'T>

Note: return can't be used outside computation expressions, use result instead.

Other operations

static member MFilter (x: seq<'Alternative>) : 'Alternative
static member inline Choice (source: 'Foldable<'Alt<'T>>) : 'Alt<'T>

Rules

empty <|> x = x
x <|> empty = x
(x <|> y) <|> z = x <|> (y <|> z)
f <!> (x <|> y) = (f <!> x) <|> (f <!> y)
(f <|> g) <*> x = (f <*> x) <|> (g <*> x)
empty <*> f = empty

Related Abstractions

From F#+

* Only <|> operation

Suggest another concrete implementation

Examples

#r @"nuget: FSharpPlus"
open FSharpPlus

// this gives [2; 3; 4; 5]
let x = [2;3] <|> [] <|> [4;5]

// but I could have written
let y = [2;3] <|> empty <|> [4;5]

// choice sample usage
let alternatives = [None; Some "Result is OK"; None ; Some "Result is still OK"]
let firstGood = choice alternatives //Some "Result is OK"

// it did something like
let fstGood = None <|> Some "Result is OK" <|>  None <|> Some "Result is still OK"

// mfilter usage
let fstMatch = mfilter ((=) 5) [1;2;3;4]    // [] -> no element found, it uses the empty value


// MonadPlus

let getLine    = async { return System.Console.ReadLine() }
let putStrLn x = async { printfn "%s" x}

let nameAndAddress = traverse (fun x -> putStrLn x >>= fun _ -> getLine) ["name";"address"]

let a:list<int> = empty
let res123      = empty <|> [1;2;3]

let inline mfilter p ma = monad.plus {
  let! a = ma
  if p a then return a else return! empty}

let mfilterRes2 = mfilter ((=)2) (Some 2)

// sample code from http://en.wikibooks.org/wiki/Haskell/MonadPlus
let pythags = monad {
  let! z = [1..50]
  let! x = [1..z]
  let! y = [x..z]
  do! guard (x*x + y*y = z*z)
  return (x, y, z)}

// same operation but using the monad.plus computation expression
let pythags' = monad.plus {
  let! z = [1..50]
  let! x = [1..z]
  let! y = [x..z]
  if (x*x + y*y = z*z) then return (x, y, z) else ()}

let allCombinations = sequence [['a'; 'b'; 'c']; ['1'; '2']]


// An Alternative is automatically a Monoid and a Functor

type Maybe<'t> =
    | Just of 't
    | Nothing 
    with
        static member Return (x:'a)     = Just x
        static member (<*>) (f, x) = 
            match (f, x) with 
            | Just f, Just x -> Just (f x) 
            | _              -> Nothing
        static member inline get_Empty () = Nothing
        static member inline (<|>) (x, y) = match x with Nothing -> y | xs -> xs

let r5 = Nothing ++ Just 5 ++ Just 6 ++ zero
let r6 = map string (Just 6)


// But not always the Monoidal behaviour is the same

let r3 = Some 2 ++ Some 1   // addition         => Some 3
let r2 = Some 2 <|> Some 1  // first success    => Some 2
Multiple items
val seq: sequence: seq<'T> -> seq<'T>

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>
Multiple items
type Choice<'T1,'T2> = | Choice1Of2 of 'T1 | Choice2Of2 of 'T2

--------------------
type Choice<'T1,'T2,'T3> = | Choice1Of3 of 'T1 | Choice2Of3 of 'T2 | Choice3Of3 of 'T3

--------------------
type Choice<'T1,'T2,'T3,'T4> = | Choice1Of4 of 'T1 | Choice2Of4 of 'T2 | Choice3Of4 of 'T3 | Choice4Of4 of 'T4

--------------------
type Choice<'T1,'T2,'T3,'T4,'T5> = | Choice1Of5 of 'T1 | Choice2Of5 of 'T2 | Choice3Of5 of 'T3 | Choice4Of5 of 'T4 | Choice5Of5 of 'T5

--------------------
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

--------------------
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
namespace FSharpPlus
val x: int list
val y: int list
val empty<'Functor<'T> (requires member Empty)> : 'Functor<'T> (requires member Empty)
<summary> A functor representing the empty value. </summary>
<category index="5">Alternative/Monadplus/Arrowplus</category>
val alternatives: string option list
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val firstGood: string option
val choice: x: 'Foldable<'Alternative<'T>> -> 'Alternative<'T>> (requires member Choice)
<summary> Reduces using alternative operator `&lt;|&gt;`. </summary>
<category index="23">Additional Functions</category>
val fstGood: string option
val fstMatch: int list
val mfilter: predicate: ('T -> bool) -> m: 'MonadZero<'T> -> 'MonadZero<'T> (requires member (>>=) and member Return and member Empty)
<summary> Generic filter operation for MonadZero. It returns all values satisfying the predicate, if the predicate returns false will use the empty value. </summary>
<category index="23">Additional Functions</category>
val getLine: Async<string>
val async: AsyncBuilder
namespace System
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
val putStrLn: x: string -> Async<unit>
val x: string
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
val nameAndAddress: Async<string list>
val traverse: f: ('T -> 'Functor<'U>) -> t: 'Traversable<'T> -> 'Functor<'Traversable<'U>> (requires member Traverse)
<summary> Map each element of a structure to an action, evaluate these actions from left to right, and collect the results. </summary>
<category index="13">Traversable</category>
val a: int list
type 'T list = List<'T>
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
val res123: int list
val mfilter: p: ('a -> bool) -> ma: 'b -> 'c (requires member (>>=) and member Empty and member Return and member Delay)
val p: ('a -> bool)
val ma: 'b (requires member (>>=) and member Empty and member Return and member Delay)
val monad<'monad<'t>> : MonadFxBuilder<'monad<'t>>
<summary> Creates a (lazy) monadic computation expression with side-effects (see http://fsprojects.github.io/FSharpPlus/computation-expressions.html for more information) </summary>
val a: 'a
val mfilterRes2: int option
val pythags: (int * int * int) list
val z: int
val x: int
val y: int
val guard: x: bool -> 'MonadPlus<unit> (requires member Return and member Empty)
<summary> Conditional failure of Alternative computations. If true it lifts the unit value, else it returns empty. Common uses of guard include conditionally signaling an error in an error monad and conditionally rejecting the current choice in an Alternative-based parser. </summary>
<category index="5">Alternative/Monadplus/Arrowplus</category>
val pythags': (int * int * int) list
val allCombinations: char list list
val sequence: t: 'Traversable<'Functor<'T>> -> 'Functor<'Traversable<'T>> (requires member Sequence)
<summary> Evaluate each action in the structure from left to right, and collect the results. </summary>
<category index="13">Traversable</category>
't
union case Maybe.Just: 't -> Maybe<'t>
union case Maybe.Nothing: Maybe<'t>
val x: 'a
'a
val f: Maybe<('a -> 'b)>
val x: Maybe<'a>
val f: ('a -> 'b)
val y: Maybe<'a>
val xs: Maybe<'a>
val r5: Maybe<int>
val zero<'Monoid (requires member Zero)> : 'Monoid (requires member Zero)
<summary> A value that represents the 0 element of a Monoid. </summary>
<category index="4">Monoid</category>
val r6: Maybe<string>
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>
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
val r3: int option
val r2: int option