You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This library allows to use some common computation expressions without writing any boiler plate code.
14
-
15
-
For [Applicatives](abstraction-applicative.html) there is single computation expression: ``applicative { .. }``. Additionally ``applicative2 { .. }`` and ``applicative3 { .. }`` exists for composed (aka layered) applicatives.
16
-
17
-
For [ZipApplicatives](abstraction-zipapplicative.html) there is a counterpart set of computation expressions: ``applicative' { .. }``, ``applicative2' { .. }`` and ``applicative3' { .. }``.
18
-
19
-
For [monadic](abstraction-monad.html) code there is a single computation expression: ``monad { .. }`` but it comes in 4 flavours:
20
-
21
-
- Delayed or strict
22
-
23
-
Delayed computations require that the type implements a TryWith, TryFinally and optionally a Delay method.
24
-
F# comes with async and seq computation expressions, both are delayed.
25
-
26
-
- It can have embedded side-effects or act as a monadplus
27
-
28
-
A monadplus can return (or yield) many times, so for example all expressions in a loop can be returned, whereas in the other model those expressions are of type unit, since a side effect is expected.
29
-
30
-
Async workflows is an example of a side-effect computation expression and seq expressions are an example of monadplus.
31
-
32
-
Side effect workflows don't have any additional requirement over the type (apart from the monad operations), but monadplus requires the additional [get_Empty and (<|>)](abstraction-alternative.html) methods.
33
-
34
-
The generic computation expression ``monad`` is a side-effect one, but it can be turned into a monadplus by accessing the ``.plus`` property.
35
-
Note that ``monad.fx`` is an alias for ``monad``: fx is used as an abbreviation for side-effects.
36
-
37
-
These computations are lazy by default, but they can be made strict by adding ``.strict`` or using a ``'``, ie ``monad.plus'``.
38
-
39
-
In other words:
40
-
41
-
- ``monad.fx`` or simply ``monad``: Lazy monadic builder. Use when you want to use side-effects instead of the additive behavior of monad plus.
42
-
- ``monad.fx.strict`` (or ``monad.fx'`` or simply ``monad.strict`` or ``monad'``) is the strict version of ``monad``.
43
-
- ``monad.plus``: Lazy additive monadic builder. Use when you expect one or more results.
44
-
- ``monad.plus'`` is the strict version of ``monad.plus``
45
-
46
-
Note that a type is either lazy or strict, but it could act as fx or plus at the same time (see below some examples). This means that we need to pay attention when using a CE over a type, if the type is lazy but with use a strict monad, we'll get strict semantics which probably would make no sense, but if we do the opposite we might run into runtime errors, fortunately a compile-time warning (or error) will prevent us.
47
-
48
-
A simple way to find out if a type is strict or lazy is to execute this in fsi: `let _ : MyType<'t> = monad { printfn "I'm strict" }`
49
-
50
-
For layered monads (monad transformers) the general rule is: the monad is strict unless at least one of its constituent types is lazy, in that case the whole monad becomes lazy.
Copy file name to clipboardExpand all lines: src/FSharpPlus/Control/Applicative.fs
+6-31Lines changed: 6 additions & 31 deletions
Original file line number
Diff line number
Diff line change
@@ -42,40 +42,15 @@ type Apply =
42
42
letf,x = f.Value, x.Value
43
43
KeyValuePair2 (Plus.Invoke a b, f x)
44
44
45
-
static member ``<*>`` (struct(f:Map<'Key,_>,x:Map<'Key,'T>),_output:Map<'Key,'U>,[<Optional>]_mthd:Apply):Map<'Key,'U>= Map (seq{
46
-
for KeyValue(k, vf)in f do
47
-
match Map.tryFind k x with
48
-
| Some vx ->yield k, vf vx
49
-
|_->()})
50
-
51
-
static member ``<*>`` (struct(f:Dictionary<'Key,_>,x:Dictionary<'Key,'T>),_output:Dictionary<'Key,'U>,[<Optional>]_mthd:Apply):Dictionary<'Key,'U>=
52
-
letdct= Dictionary ()
53
-
for KeyValue(k, vf)in f do
54
-
match x.TryGetValue k with
55
-
|true, vx -> dct.Add (k, vf vx)
56
-
|_->()
57
-
dct
58
-
59
-
static member ``<*>`` (struct(f:IDictionary<'Key,_>,x:IDictionary<'Key,'T>),_output:IDictionary<'Key,'U>,[<Optional>]_mthd:Apply):IDictionary<'Key,'U>=
60
-
letdct= Dictionary ()
61
-
for KeyValue(k, vf)in f do
62
-
match x.TryGetValue k with
63
-
|true, vx -> dct.Add (k, vf vx)
64
-
|_->()
65
-
dct :> IDictionary<'Key,'U>
66
-
67
-
static member ``<*>`` (struct(f:IReadOnlyDictionary<'Key,_>,x:IReadOnlyDictionary<'Key,'T>),_output:IReadOnlyDictionary<'Key,'U>,[<Optional>]_mthd:Apply):IReadOnlyDictionary<'Key,'U>=
68
-
letdct= Dictionary ()
69
-
for KeyValue(k, vf)in f do
70
-
match x.TryGetValue k with
71
-
|true, vx -> dct.Add (k, vf vx)
72
-
|_->()
73
-
dct :> IReadOnlyDictionary<'Key,'U>
45
+
static member ``<*>`` (struct(f:Map<'Key,_>,x:Map<'Key,'T>),_output:Map<'Key,'U>,[<Optional>]_mthd:Apply):Map<'Key,'U>= Map.apply f x
46
+
static member ``<*>`` (struct(f:Dictionary<'Key,_>,x:Dictionary<'Key,'T>),_output:Dictionary<'Key,'U>,[<Optional>]_mthd:Apply):Dictionary<'Key,'U>= Dictionary.apply f x
47
+
static member ``<*>`` (struct(f:IDictionary<'Key,_>,x:IDictionary<'Key,'T>),_output:IDictionary<'Key,'U>,[<Optional>]_mthd:Apply):IDictionary<'Key,'U>= Dict.apply f x
48
+
static member ``<*>`` (struct(f:IReadOnlyDictionary<'Key,_>,x:IReadOnlyDictionary<'Key,'T>),_output:IReadOnlyDictionary<'Key,'U>,[<Optional>]_mthd:Apply):IReadOnlyDictionary<'Key,'U>= IReadOnlyDictionary.apply f x
static member ``<*>`` (struct(f:Expr<'T->'U>,x:Expr<'T>),_output:Expr<'U>,[<Optional>]_mthd:Apply)= Expr.Cast<'U>(Expr.Application (f, x))
77
52
#endif
78
-
static member``<*>`` (struct(f:('T->'U) ResizeArray,x:'T ResizeArray),_output:'U ResizeArray,[<Optional>]_mthd:Apply)= ResizeArray.apply f x : 'U ResizeArray
53
+
static member ``<*>`` (struct(f:('T->'U) ResizeArray,x:'T ResizeArray),_output:'U ResizeArray,[<Optional>]_mthd:Apply)= ResizeArray.apply f x : 'U ResizeArray
79
54
80
55
static member inlineInvoke(f:'``Applicative<'T->'U>``)(x:'``Applicative<'T>``):'``Applicative<'U>`` =
81
56
let inlinecall(mthd :^M,input1:^I1,input2:^I2,output:^R)=
Copy file name to clipboardExpand all lines: src/FSharpPlus/Control/Foldable.fs
+7Lines changed: 7 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -147,6 +147,10 @@ type FoldMap =
147
147
static member inlineFoldMap(x:Set<_>,f,[<Optional>]_impl:FoldMap)= Seq.fold (fun x y -> Plus.Invoke x (f y))(Zero.Invoke ()) x
148
148
static member inlineFoldMap(x:_ [],f,[<Optional>]_impl:FoldMap)= Array.fold (fun x y -> Plus.Invoke x (f y))(Zero.Invoke ()) x
149
149
150
+
static member inlineFoldMap(x:Map<_,_>,f,[<Optional>]_impl:FoldMap)= Map.fold (fun x _ y -> Plus.Invoke x (f y))(Zero.Invoke ()) x
151
+
static member inlineFoldMap(x:IDictionary<_,_>,f,[<Optional>]_impl:FoldMap)= Dict.fold (fun x _ y -> Plus.Invoke x (f y))(Zero.Invoke ()) x
152
+
static member inlineFoldMap(x:IReadOnlyDictionary<_,_>,f,[<Optional>]_impl:FoldMap)= IReadOnlyDictionary.fold (fun x _ y -> Plus.Invoke x (f y))(Zero.Invoke ()) x
153
+
150
154
static member inlineInvoke(f:'T->'Monoid)(x:'``Foldable'<T>``):'Monoid =
151
155
let inlinecall_2(a:^a,b:^b,f)=((^aor^b):(static memberFoldMap:_*_*_->_) b, f, a)
152
156
let inlinecall(a:'a,b:'b,f)= call_2 (a, b, f)
@@ -185,6 +189,9 @@ type Fold =
185
189
static memberFold(x:list<_>,f,z ,[<Optional>]_impl:Fold )= List.fold f z x
186
190
static memberFold(x:Set<_>,f,z ,[<Optional>]_impl:Fold )= Set.fold f z x
187
191
static memberFold(x:_ [],f,z ,[<Optional>]_impl:Fold )= Array.fold f z x
192
+
static memberFold(x:Map<_,_>,f,z ,[<Optional>]_impl:Fold )= Map.fold (fun s _ -> f s) z x
193
+
static memberFold(x:IDictionary<_,_>,f,z ,[<Optional>]_impl:Fold )= Dict.fold (fun s _ -> f s) z x
194
+
static memberFold(x:IReadOnlyDictionary<_,_>,f,z ,[<Optional>]_impl:Fold )= IReadOnlyDictionary.fold (fun s _ -> f s) z x
188
195
189
196
static member inlineInvoke(folder:'State->'T->'State)(state:'State)(foldable:'``Foldable'<T>``):'State =
190
197
let inlinecall_2(a:^a,b:^b,f,z)=((^aor^b):(static memberFold:_*_*_*_->_) b, f, z, a)
static memberZip((x:seq<'T>,y:seq<'U>,_output:seq<'T*'U>),_mthd:Zip)= Seq.zip x y
209
209
static memberZip((x:IDictionary<'K,'T>,y:IDictionary<'K,'U>,_output:IDictionary<'K,'T*'U>),_mthd:Zip)= Dict.zip x y
210
210
static memberZip((x:IReadOnlyDictionary<'K,'T>,y:IReadOnlyDictionary<'K,'U>,_output:IReadOnlyDictionary<'K,'T*'U>),_mthd:Zip)= IReadOnlyDictionary.zip x y
211
-
static memberZip((x:Dictionary<'K,'T>,y:Dictionary<'K,'U>,_output:Dictionary<'K,'T*'U>),_mthd:Zip)=Dict.zip x y :?> Dictionary<'K,'T*'U>
211
+
static memberZip((x:Dictionary<'K,'T>,y:Dictionary<'K,'U>,_output:Dictionary<'K,'T*'U>),_mthd:Zip)=Dictionary.zip x y
212
212
static memberZip((x:Map<'K,'T>,y:Map<'K,'U>,_output:Map<'K,'T*'U>),_mthd:Zip)= Map.zip x y
213
213
static memberZip((f:'R ->'T ,g:'R ->'U ,_output:'R ->'T * 'U ),_mthd:Zip)=fun x ->(f x, g x)
214
214
static memberZip((f:Func<'R,'T>,g:Func<'R,'U>,_output:Func<'R,'T*'U>),_mthd:Zip)= Func<_,_>(fun x ->(f.Invoke x, g.Invoke x))
0 commit comments