FSharpPlus


Zip Applicative (aka Non-sequential Applicative)

A functor with application, providing operations to embed pure expressions (pur), run computations pointwise and/or paralell and combine their results (<.>).


Minimal complete definition

static member Pure (x: 'T) : 'ZipApplicative<'T>
static member (<.>) (f: 'ZipApplicative<'T -> 'U>, x: 'ZipApplicative<'T>) : 'ZipApplicative<'U>

Other operations

static member Zip (x1: 'ZipApplicative<'T1>, x2: 'ZipApplicative<'T2>) : 'ZipApplicative<'T1 * 'T2>
static member Unzip (x: 'ZipApplicative<'T1 * 'T2>) : 'ZipApplicative<'T1> * 'ZipApplicative<'T2>
static member Map2 (f: 'T1 -> 'T2 -> 'T, x1: 'ZipApplicative<'T1>, x2: 'ZipApplicative<'T2>) : 'ZipApplicative<'T>
static member Map3 (f: 'T1 -> 'T2 -> 'T3 -> 'T, x1: 'ZipApplicative<'T1>, x2: 'ZipApplicative<'T2>, x3: 'ZipApplicative<'T3>) : 'ZipApplicative<'T>

Rules

Since ZipApplicatives are Applicatives they obey the same applicative rules:

pur id <.> v = v
pur (<<) <.> u <.> v <.> w = u <.> (v <.> w)
pur f <*> pur x = pur (f x)
u <*> pur y = pur ((|>) y) <.> u

But they have some additional rules:

zip x y = tuple2 <!> x <.> y
unzip = map fst &&& map snd
id = unzip >> (<||) zip = (<||) zip >> unzip

Related Abstractions

Concrete implementations

From F#

From F#+

Only for <*> operation: - array<'T> - ResizeArray<'T> - Map<'Key, 'T> - Dictionary<'Key, 'T> - IDictionary<'Key, 'T> - IReadOnlyDictionary<'Key, 'T>

Suggest another concrete implementation

Examples

#r @"nuget: FSharpPlus"
open FSharpPlus

let (x, y) = zip (async { return 1 }) (async { return '2' }) |> Async.RunSynchronously
// val y: char = '2'


// crossproduct vs pointwise operations

let arr1 = (+) <!> [|1;2;3|] <*> [|10;20;30|]
let arr2 = (+) <!> [|1;2;3|] <.> [|10;20;30|]

// val arr1: int array = [|11; 21; 31; 12; 22; 32; 13; 23; 33|]
// val arr2: int array = [|11; 22; 33|]


// Validations

let validated = applicative2' {
    let! x = async { return Ok 1 }
    and! y = async { return Error ["Error1"] }
    and! z = async { return Error ["Error2"] }
    return x + y + z
}

validated |> Async.RunSynchronously
// val it: Result<int,string list> = Error ["Error1"; "Error2"]
val id: x: 'T -> 'T
val fst: tuple: ('T1 * 'T2) -> 'T1
val snd: tuple: ('T1 * 'T2) -> 'T2
namespace FSharpPlus
val x: int
val y: char
val zip: source1: 'ZipFunctor<'T1> -> source2: 'ZipFunctor<'T2> -> 'ZipFunctor<'T1 * 'T2> (requires member Zip)
<summary> Zips (tuple) two functors. </summary>
<remarks> For collections, if one collection is shorter, excess elements are discarded from the right end of the longer collection. </remarks>
<category index="1">Functor</category>
val async: AsyncBuilder
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: Async<'T option> seq -> 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> ...

--------------------
type Async<'T>
static member Async.RunSynchronously: computation: Async<'T> * ?timeout: int * ?cancellationToken: System.Threading.CancellationToken -> 'T
val arr1: int array
val arr2: int array
val validated: Async<Result<int,string list>>
val applicative2'<'ZipApplicative1<ZipApplicative2<'T>>> : ZipApplicativeBuilder2<'ZipApplicative1<ZipApplicative2<'T>>>
<summary> Creates a (non sequential) applicative computation expression which compose effects of two Applicatives. </summary>
union case Result.Ok: ResultValue: 'T -> Result<'T,'TError>
val y: int
union case Result.Error: ErrorValue: 'TError -> Result<'T,'TError>
val z: int