3 people like it.
Like the snippet!
Update Monad in F# based on Tomas Petricek article
This is 100% based on tomas petricek blog article.
there has been some small additions in regards to adding Result type
and handling Monoids for the Writer Part.
go check the following blog article : http://tomasp.net/blog/2014/update-monads/
Comment appreciated + bear in mind that performance wise, the Monoid Combine operator, could be greatly improved and more.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
|
/// This is 100% based on tomas petricek blog article.
/// there has been some small additions in regards to adding Result type
/// and handling Monoids for the Writer Part.
/// go check the following blog article : http://tomasp.net/blog/2014/update-monads/
/// Comment appreciated + bear in mind that performance wise, the Monoid Combine operator,
/// could be greatly improved and more.
[<AutoOpen>]
module Monoid =
type IMonoid<'M> =
abstract member Empty : (unit -> 'M)
abstract member Combine : ('M * 'M -> 'M)
let listMonoid =
{ new IMonoid<list<'T>> with
member __.Empty = fun () -> []
member __.Combine = fun (l1,l2) -> l1 @ l2
}
let arrayMonoid =
{ new IMonoid<'T []> with
member __.Empty = fun () -> [||]
member __.Combine = fun (a1,a2) -> Array.append a1 a2
}
let unitMonoid =
{ new IMonoid<_> with
member __.Empty = fun () -> ()
member __.Combine = fun (_,_) -> ()
}
[<AutoOpen>]
module UpdateResult =
[<NoComparison>]
[<NoEquality>]
type Result<'Update, 'T> =
| Success of 'Update * 'T
// It is bad practice to use a string as a failure description
// Let to the user to update the Failure payload to be a proper type or something
// of the sort
| Failure of string
[<NoComparison>]
[<NoEquality>]
type UpdateMonad<'TState, 'TUpdate, 'T> = UM of ('TState -> Result<'TUpdate, 'T>)
[<NoComparison>]
[<NoEquality>]
type DelayedUM<'TState, 'TUpdate, 'T> = DelayedUM of (unit -> UpdateMonad<'TState, 'TUpdate, 'T>)
let inline unit< 'T, ^S when ^S : (static member Unit : IMonoid<'T> -> ^S) > (m : IMonoid<'T>) : ^S =
(^S : (static member Unit : IMonoid<'T> -> ^S) (m))
/// Invokes Combine operation on a pair of ^S values
let inline combine< 'T, ^S when ^S : (static member Combine : IMonoid<'T> * ^S * ^S -> ^S ) > m a b : ^S =
(^S : (static member Combine : IMonoid<'T> * ^S * ^S -> ^S) (m, a, b))
/// Invokes Apply operation on state and update ^S * ^U
let inline apply< 'T, ^S, ^U when ^U : (static member Apply : IMonoid<'T> * ^S * ^U -> ^S )> m s a : ^S =
(^U : (static member Apply : IMonoid<'T> * ^S * ^U -> ^S) (m, s, a))
type UpdateBuilder<'M>(monoid: IMonoid<'M>) =
member inline __.Bind(DelayedUM delayed, f:'T -> UpdateMonad<'S, 'U, 'R>) : UpdateMonad<'S, 'U, 'R>=
UM (fun state ->
// Run the first computation to get first update
// 'u1', then run 'f' to get second computation
let (UM update1) = delayed ()
match update1 state with
| Success (update1,value1) ->
let (UM update2) = f value1
// Apply 'u1' to original state & run second computation
// then return result with combined state updates
match update2 (apply monoid state update1) with
| Success (update2,value2) ->
let res = combine monoid update1 update2
Success (res,value2)
| Failure failure -> Failure failure
| Failure failure -> Failure failure
)
member inline __.Return(value:'T) : UpdateMonad<'S, 'U, 'T> =
let update = unit monoid
UM (fun _ -> Success (update,value))
member inline __.ReturnFrom(DelayedUM update : DelayedUM<'S, 'U, 'T>) : UpdateMonad<'S, 'U, 'T> =
update ()
member inline x.Yield(value:'T) : UpdateMonad<'S, 'U, 'T> = x.Return value
member inline x.YieldFrom(delayedUM) = x.ReturnFrom delayedUM
member inline this.Zero() : UpdateMonad<'S, 'U, unit> = this.Return ()
member inline __.Delay(f:unit -> UpdateMonad<'State, 'Update, 'T>) = f
member inline __.Run(f:unit -> UpdateMonad<'State, 'Update, 'T>) = DelayedUM f
member inline this.Combine(update : UpdateMonad<'S, 'U, 'T>, delayedUM : unit -> UpdateMonad<'S, 'U, 'T>) : UpdateMonad<'S, 'U, 'T>=
this.Bind(DelayedUM (fun _ -> update), fun _ -> delayedUM())
member inline this.TryFinally(body, compensation) =
try this.ReturnFrom(body())
finally compensation()
member inline this.TryWith(body : unit -> DelayedUM<'S,'U,'T>, handler: exn -> UpdateMonad<'S, 'U, 'T>) : UpdateMonad<'S, 'U, 'T> =
try this.ReturnFrom(body())
with e -> handler e
member inline this.Using(disposable:#System.IDisposable, body : 'a -> DelayedUM<'S, 'U, 'T>) =
let body' = fun () -> body disposable
this.TryFinally(body', fun () ->
match disposable with
| null -> ()
| disp -> disp.Dispose())
member inline this.While(guard: unit -> bool, body: unit -> UpdateMonad<'S, 'U, unit>) : DelayedUM<'S, 'U, unit> =
let rec loop () =
if guard() then
this.Bind(DelayedUM body, loop)
else
this.Zero()
DelayedUM( fun () -> loop())
member inline this.For(sequence:seq<'a>, body: 'a -> UpdateMonad<'S, 'U, unit>) : UpdateMonad<'S, 'U, unit>=
this.Using(sequence.GetEnumerator(),fun enum ->
this.While(enum.MoveNext,
this.Delay(fun () -> body enum.Current)))
module ReaderResult =
let reader = UpdateBuilder(unitMonoid)
type ReaderUpdate =
| NoUpdate
static member Unit(_:IMonoid<'T>) = NoUpdate
static member Combine(_:IMonoid<'T>, NoUpdate, NoUpdate) = NoUpdate
static member Apply(_:IMonoid<'T>, s, NoUpdate) = s
/// Read the current state (int) and return it as 'int'
let read = DelayedUM ( fun() -> UM (fun (s:'T) -> Success (NoUpdate, s)) )
/// Run computation and return the result
let readRun (s:'T) (DelayedUM f) =
let (UM update) = f()
update s
/// Returns state + 1
let demo1 = reader {
let! v = read
printfn "side effect"
return v + 1
}
/// Returns the result of demo1 + 1
let demo2 = reader {
printfn "hello"
let! v = demo1
return v + 1
}
// Run it with state 40
let resRead = demo2 |> readRun 40
module WriterResult =
/// Writer monad has no readable state
type WriterState = NoState
type WriterUpdate<'M> =
| WU of 'M
static member Unit(monoid : IMonoid<'T>) = WU (monoid.Empty())
static member Combine(monoid : IMonoid<'T>, WU m1, WU m2) = WU (monoid.Combine(m1,m2))
/// Applying updates to state does not affect the state
static member Apply(_ : IMonoid<'T>, NoState, _) = NoState
let inline write value =
DelayedUM( fun () -> UM (fun _ -> Success (WU value, ())))
/// Runs a "writer monad computation" and returns
let writeRun (DelayedUM delayed) =
let (UM update) = delayed()
update NoState
let writerList () = UpdateBuilder<'a list>(listMonoid)
let inline writeList value = write value
let demoWriter =
writerList () {
for i in 1..10 do
do! writeList [i]
}
let resWriter = demoWriter |> writeRun
module StateResult =
/// Wraps a state of type 'T
type StateState<'T> = State of 'T
/// Represents updates on state of type 'T
type StateUpdate<'T> =
| Set of 'T
| SetNop
/// Empty update - do not change the state
static member Unit(_ : IMonoid<'T>) = SetNop
/// Combine updates - return the latest (rightmost) 'Set' update
static member Combine(_ : IMonoid<'T>, a, b) =
match a, b with
| SetNop, v | v, SetNop -> v
| Set _ , Set b -> Set b
/// Apply update to a state - the 'Set' update changes the state
static member Apply(_ : IMonoid<'T>, s, p) =
match p with
| SetNop -> s
| Set s -> State s
/// Put the state to the specified value
let put s = UM (fun _ -> Success (Set s,()))
/// Get the current state
let get = UM (fun (State s) -> Success (SetNop, s))
/// Run a computation using a specified initial state
let setRun s (UM f) = f (State s)
|
Multiple items
type AutoOpenAttribute =
inherit Attribute
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
member Path : string
Full name: Microsoft.FSharp.Core.AutoOpenAttribute
--------------------
new : unit -> AutoOpenAttribute
new : path:string -> AutoOpenAttribute
type IMonoid<'M> =
interface
abstract member Combine : ('M * 'M -> 'M)
abstract member Empty : (unit -> 'M)
end
Full name: Script.Monoid.IMonoid<_>
abstract member IMonoid.Empty : (unit -> 'M)
Full name: Script.Monoid.IMonoid`1.Empty
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
abstract member IMonoid.Combine : ('M * 'M -> 'M)
Full name: Script.Monoid.IMonoid`1.Combine
val listMonoid : IMonoid<'T list>
Full name: Script.Monoid.listMonoid
type 'T list = List<'T>
Full name: Microsoft.FSharp.Collections.list<_>
val __ : IMonoid<'T list>
property IMonoid.Combine: 'T list * 'T list -> 'T list
val l1 : 'T list
val l2 : 'T list
val arrayMonoid : IMonoid<'T []>
Full name: Script.Monoid.arrayMonoid
val __ : IMonoid<'T []>
property IMonoid.Combine: 'T [] * 'T [] -> 'T []
val a1 : 'T []
val a2 : 'T []
module Array
from Microsoft.FSharp.Collections
val append : array1:'T [] -> array2:'T [] -> 'T []
Full name: Microsoft.FSharp.Collections.Array.append
val unitMonoid : IMonoid<unit>
Full name: Script.Monoid.unitMonoid
val __ : IMonoid<unit>
property IMonoid.Combine: unit * unit -> unit
Multiple items
type NoComparisonAttribute =
inherit Attribute
new : unit -> NoComparisonAttribute
Full name: Microsoft.FSharp.Core.NoComparisonAttribute
--------------------
new : unit -> NoComparisonAttribute
Multiple items
type NoEqualityAttribute =
inherit Attribute
new : unit -> NoEqualityAttribute
Full name: Microsoft.FSharp.Core.NoEqualityAttribute
--------------------
new : unit -> NoEqualityAttribute
type Result<'Update,'T> =
| Success of 'Update * 'T
| Failure of string
Full name: Script.UpdateResult.Result<_,_>
union case Result.Success: 'Update * 'T -> Result<'Update,'T>
Multiple items
union case Result.Failure: string -> Result<'Update,'T>
--------------------
active recognizer Failure: exn -> string option
Full name: Microsoft.FSharp.Core.Operators.( |Failure|_| )
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = System.String
Full name: Microsoft.FSharp.Core.string
type UpdateMonad<'TState,'TUpdate,'T> = | UM of ('TState -> Result<'TUpdate,'T>)
Full name: Script.UpdateResult.UpdateMonad<_,_,_>
union case UpdateMonad.UM: ('TState -> Result<'TUpdate,'T>) -> UpdateMonad<'TState,'TUpdate,'T>
Multiple items
union case DelayedUM.DelayedUM: (unit -> UpdateMonad<'TState,'TUpdate,'T>) -> DelayedUM<'TState,'TUpdate,'T>
--------------------
type DelayedUM<'TState,'TUpdate,'T> = | DelayedUM of (unit -> UpdateMonad<'TState,'TUpdate,'T>)
Full name: Script.UpdateResult.DelayedUM<_,_,_>
Multiple items
val unit : m:IMonoid<'T> -> 'S (requires member Unit)
Full name: Script.UpdateResult.unit
--------------------
type unit = Unit
Full name: Microsoft.FSharp.Core.unit
val m : IMonoid<'T>
val combine : m:IMonoid<'T> -> a:'S -> b:'S -> 'S (requires member Combine)
Full name: Script.UpdateResult.combine
val a : 'S (requires member Combine)
val b : 'S (requires member Combine)
val apply : m:IMonoid<'T> -> s:'S -> a:'U -> 'S (requires member Apply)
Full name: Script.UpdateResult.apply
val s : 'S
val a : 'U (requires member Apply)
Multiple items
type UpdateBuilder<'M> =
new : monoid:IMonoid<'M> -> UpdateBuilder<'M>
member Bind : DelayedUM<'S,'U,'T> * f:('T -> UpdateMonad<'S,'U,'R>) -> UpdateMonad<'S,'U,'R> (requires member Combine and member Apply)
member Combine : update:UpdateMonad<'S,'U,'T> * delayedUM:(unit -> UpdateMonad<'S,'U,'T>) -> UpdateMonad<'S,'U,'T> (requires member Combine and member Apply)
member Delay : f:(unit -> UpdateMonad<'State,'Update,'T>) -> (unit -> UpdateMonad<'State,'Update,'T>)
member For : sequence:seq<'a> * body:('a -> UpdateMonad<'S,'U,unit>) -> UpdateMonad<'S,'U,unit> (requires member Apply and member Combine and member Unit)
member Return : value:'T -> UpdateMonad<'S,'U,'T> (requires member Unit)
member ReturnFrom : DelayedUM<'S,'U,'T> -> UpdateMonad<'S,'U,'T>
member Run : f:(unit -> UpdateMonad<'State,'Update,'T>) -> DelayedUM<'State,'Update,'T>
member TryFinally : body:(unit -> DelayedUM<'a,'b,'c>) * compensation:(unit -> unit) -> UpdateMonad<'a,'b,'c>
member TryWith : body:(unit -> DelayedUM<'S,'U,'T>) * handler:(exn -> UpdateMonad<'S,'U,'T>) -> UpdateMonad<'S,'U,'T>
...
Full name: Script.UpdateResult.UpdateBuilder<_>
--------------------
new : monoid:IMonoid<'M> -> UpdateBuilder<'M>
val monoid : IMonoid<'M>
member UpdateBuilder.Bind : DelayedUM<'S,'U,'T> * f:('T -> UpdateMonad<'S,'U,'R>) -> UpdateMonad<'S,'U,'R> (requires member Combine and member Apply)
Full name: Script.UpdateResult.UpdateBuilder`1.Bind
val delayed : (unit -> UpdateMonad<'S,'U,'T>) (requires member Combine and member Apply)
val f : ('T -> UpdateMonad<'S,'U,'R>) (requires member Combine and member Apply)
val state : 'S
val update1 : ('S -> Result<'U,'T>) (requires member Combine and member Apply)
val update1 : 'U (requires member Combine and member Apply)
val value1 : 'T
val update2 : ('S -> Result<'U,'R>) (requires member Combine and member Apply)
val update2 : 'U (requires member Combine and member Apply)
val value2 : 'R
val res : 'U (requires member Combine and member Apply)
union case Result.Failure: string -> Result<'Update,'T>
val failure : string
val __ : UpdateBuilder<'M>
member UpdateBuilder.Return : value:'T -> UpdateMonad<'S,'U,'T> (requires member Unit)
Full name: Script.UpdateResult.UpdateBuilder`1.Return
val value : 'T
val update : 'U (requires member Unit)
member UpdateBuilder.ReturnFrom : DelayedUM<'S,'U,'T> -> UpdateMonad<'S,'U,'T>
Full name: Script.UpdateResult.UpdateBuilder`1.ReturnFrom
val update : (unit -> UpdateMonad<'S,'U,'T>)
val x : UpdateBuilder<'M>
member UpdateBuilder.Yield : value:'T -> UpdateMonad<'S,'U,'T> (requires member Unit)
Full name: Script.UpdateResult.UpdateBuilder`1.Yield
member UpdateBuilder.Return : value:'T -> UpdateMonad<'S,'U,'T> (requires member Unit)
member UpdateBuilder.YieldFrom : delayedUM:DelayedUM<'a,'b,'c> -> UpdateMonad<'a,'b,'c>
Full name: Script.UpdateResult.UpdateBuilder`1.YieldFrom
val delayedUM : DelayedUM<'a,'b,'c>
member UpdateBuilder.ReturnFrom : DelayedUM<'S,'U,'T> -> UpdateMonad<'S,'U,'T>
val this : UpdateBuilder<'M>
member UpdateBuilder.Zero : unit -> UpdateMonad<'S,'U,unit> (requires member Unit)
Full name: Script.UpdateResult.UpdateBuilder`1.Zero
member UpdateBuilder.Delay : f:(unit -> UpdateMonad<'State,'Update,'T>) -> (unit -> UpdateMonad<'State,'Update,'T>)
Full name: Script.UpdateResult.UpdateBuilder`1.Delay
val f : (unit -> UpdateMonad<'State,'Update,'T>)
member UpdateBuilder.Run : f:(unit -> UpdateMonad<'State,'Update,'T>) -> DelayedUM<'State,'Update,'T>
Full name: Script.UpdateResult.UpdateBuilder`1.Run
member UpdateBuilder.Combine : update:UpdateMonad<'S,'U,'T> * delayedUM:(unit -> UpdateMonad<'S,'U,'T>) -> UpdateMonad<'S,'U,'T> (requires member Combine and member Apply)
Full name: Script.UpdateResult.UpdateBuilder`1.Combine
val update : UpdateMonad<'S,'U,'T> (requires member Combine and member Apply)
val delayedUM : (unit -> UpdateMonad<'S,'U,'T>) (requires member Combine and member Apply)
member UpdateBuilder.Bind : DelayedUM<'S,'U,'T> * f:('T -> UpdateMonad<'S,'U,'R>) -> UpdateMonad<'S,'U,'R> (requires member Combine and member Apply)
member UpdateBuilder.TryFinally : body:(unit -> DelayedUM<'a,'b,'c>) * compensation:(unit -> unit) -> UpdateMonad<'a,'b,'c>
Full name: Script.UpdateResult.UpdateBuilder`1.TryFinally
val body : (unit -> DelayedUM<'a,'b,'c>)
val compensation : (unit -> unit)
member UpdateBuilder.TryWith : body:(unit -> DelayedUM<'S,'U,'T>) * handler:(exn -> UpdateMonad<'S,'U,'T>) -> UpdateMonad<'S,'U,'T>
Full name: Script.UpdateResult.UpdateBuilder`1.TryWith
val body : (unit -> DelayedUM<'S,'U,'T>)
val handler : (exn -> UpdateMonad<'S,'U,'T>)
type exn = System.Exception
Full name: Microsoft.FSharp.Core.exn
val e : exn
member UpdateBuilder.Using : disposable:'a * body:('a -> DelayedUM<'S,'U,'T>) -> UpdateMonad<'S,'U,'T> (requires 'a :> System.IDisposable and 'a : null)
Full name: Script.UpdateResult.UpdateBuilder`1.Using
val disposable : 'a (requires 'a :> System.IDisposable and 'a : null)
namespace System
type IDisposable =
member Dispose : unit -> unit
Full name: System.IDisposable
val body : ('a -> DelayedUM<'S,'U,'T>) (requires 'a :> System.IDisposable and 'a : null)
val body' : (unit -> DelayedUM<'S,'U,'T>)
member UpdateBuilder.TryFinally : body:(unit -> DelayedUM<'a,'b,'c>) * compensation:(unit -> unit) -> UpdateMonad<'a,'b,'c>
val disp : 'a (requires 'a :> System.IDisposable and 'a : null)
System.IDisposable.Dispose() : unit
member UpdateBuilder.While : guard:(unit -> bool) * body:(unit -> UpdateMonad<'S,'U,unit>) -> DelayedUM<'S,'U,unit> (requires member Apply and member Combine and member Unit)
Full name: Script.UpdateResult.UpdateBuilder`1.While
val guard : (unit -> bool)
type bool = System.Boolean
Full name: Microsoft.FSharp.Core.bool
val body : (unit -> UpdateMonad<'S,'U,unit>) (requires member Apply and member Combine and member Unit)
val loop : (unit -> UpdateMonad<'S,'U,unit>) (requires member Apply and member Combine and member Unit)
member UpdateBuilder.Zero : unit -> UpdateMonad<'S,'U,unit> (requires member Unit)
member UpdateBuilder.For : sequence:seq<'a> * body:('a -> UpdateMonad<'S,'U,unit>) -> UpdateMonad<'S,'U,unit> (requires member Apply and member Combine and member Unit)
Full name: Script.UpdateResult.UpdateBuilder`1.For
val sequence : seq<'a>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Core.Operators.seq
--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>
Full name: Microsoft.FSharp.Collections.seq<_>
val body : ('a -> UpdateMonad<'S,'U,unit>) (requires member Apply and member Combine and member Unit)
member UpdateBuilder.Using : disposable:'a * body:('a -> DelayedUM<'S,'U,'T>) -> UpdateMonad<'S,'U,'T> (requires 'a :> System.IDisposable and 'a : null)
System.Collections.Generic.IEnumerable.GetEnumerator() : System.Collections.Generic.IEnumerator<'a>
val enum : System.Collections.Generic.IEnumerator<'a>
member UpdateBuilder.While : guard:(unit -> bool) * body:(unit -> UpdateMonad<'S,'U,unit>) -> DelayedUM<'S,'U,unit> (requires member Apply and member Combine and member Unit)
System.Collections.IEnumerator.MoveNext() : bool
member UpdateBuilder.Delay : f:(unit -> UpdateMonad<'State,'Update,'T>) -> (unit -> UpdateMonad<'State,'Update,'T>)
property System.Collections.Generic.IEnumerator.Current: 'a
val reader : UpdateBuilder<unit>
Full name: Script.ReaderResult.reader
type ReaderUpdate =
| NoUpdate
static member Apply : IMonoid<'T> * s:'a * NoUpdate:ReaderUpdate -> 'a
static member Combine : IMonoid<'T> * NoUpdate:ReaderUpdate * NoUpdate:ReaderUpdate -> ReaderUpdate
static member Unit : IMonoid<'T> -> ReaderUpdate
Full name: Script.ReaderResult.ReaderUpdate
union case ReaderUpdate.NoUpdate: ReaderUpdate
static member ReaderUpdate.Unit : IMonoid<'T> -> ReaderUpdate
Full name: Script.ReaderResult.ReaderUpdate.Unit
static member ReaderUpdate.Combine : IMonoid<'T> * NoUpdate:ReaderUpdate * NoUpdate:ReaderUpdate -> ReaderUpdate
Full name: Script.ReaderResult.ReaderUpdate.Combine
static member ReaderUpdate.Apply : IMonoid<'T> * s:'a * NoUpdate:ReaderUpdate -> 'a
Full name: Script.ReaderResult.ReaderUpdate.Apply
val s : 'a
val read : DelayedUM<'T,ReaderUpdate,'T>
Full name: Script.ReaderResult.read
Read the current state (int) and return it as 'int'
val s : 'T
val readRun : s:'T -> DelayedUM<'T,'a,'b> -> Result<'a,'b>
Full name: Script.ReaderResult.readRun
Run computation and return the result
val f : (unit -> UpdateMonad<'T,'a,'b>)
val update : ('T -> Result<'a,'b>)
val demo1 : DelayedUM<int,ReaderUpdate,int>
Full name: Script.ReaderResult.demo1
Returns state + 1
val v : int
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val demo2 : DelayedUM<int,ReaderUpdate,int>
Full name: Script.ReaderResult.demo2
Returns the result of demo1 + 1
val resRead : Result<ReaderUpdate,int>
Full name: Script.ReaderResult.resRead
type WriterState = | NoState
Full name: Script.WriterResult.WriterState
Writer monad has no readable state
union case WriterState.NoState: WriterState
type WriterUpdate<'M> =
| WU of 'M
static member Apply : IMonoid<'T> * NoState:WriterState * 'a -> WriterState
static member Combine : monoid:IMonoid<'T> * WriterUpdate<'T> * WriterUpdate<'T> -> WriterUpdate<'T>
static member Unit : monoid:IMonoid<'T> -> WriterUpdate<'T>
Full name: Script.WriterResult.WriterUpdate<_>
union case WriterUpdate.WU: 'M -> WriterUpdate<'M>
static member WriterUpdate.Unit : monoid:IMonoid<'T> -> WriterUpdate<'T>
Full name: Script.WriterResult.WriterUpdate`1.Unit
val monoid : IMonoid<'T>
property IMonoid.Empty: unit -> 'T
static member WriterUpdate.Combine : monoid:IMonoid<'T> * WriterUpdate<'T> * WriterUpdate<'T> -> WriterUpdate<'T>
Full name: Script.WriterResult.WriterUpdate`1.Combine
val m1 : 'T
val m2 : 'T
property IMonoid.Combine: 'T * 'T -> 'T
static member WriterUpdate.Apply : IMonoid<'T> * NoState:WriterState * 'a -> WriterState
Full name: Script.WriterResult.WriterUpdate`1.Apply
Applying updates to state does not affect the state
val write : value:'a -> DelayedUM<'b,WriterUpdate<'a>,unit>
Full name: Script.WriterResult.write
val value : 'a
val writeRun : DelayedUM<WriterState,'a,'b> -> Result<'a,'b>
Full name: Script.WriterResult.writeRun
Runs a "writer monad computation" and returns
val delayed : (unit -> UpdateMonad<WriterState,'a,'b>)
val update : (WriterState -> Result<'a,'b>)
val writerList : unit -> UpdateBuilder<'a list>
Full name: Script.WriterResult.writerList
val writeList : value:'a -> DelayedUM<'b,WriterUpdate<'a>,unit>
Full name: Script.WriterResult.writeList
val demoWriter : DelayedUM<WriterState,WriterUpdate<int list>,unit>
Full name: Script.WriterResult.demoWriter
val i : int
val resWriter : Result<WriterUpdate<int list>,unit>
Full name: Script.WriterResult.resWriter
module StateResult
from Script
type StateState<'T> = | State of 'T
Full name: Script.StateResult.StateState<_>
Wraps a state of type 'T
union case StateState.State: 'T -> StateState<'T>
type StateUpdate<'T> =
| Set of 'T
| SetNop
static member Apply : IMonoid<'T> * s:StateState<'a> * p:StateUpdate<'a> -> StateState<'a>
static member Combine : IMonoid<'T> * a:StateUpdate<'a> * b:StateUpdate<'a> -> StateUpdate<'a>
static member Unit : IMonoid<'T> -> StateUpdate<'a>
Full name: Script.StateResult.StateUpdate<_>
Represents updates on state of type 'T
Multiple items
union case StateUpdate.Set: 'T -> StateUpdate<'T>
--------------------
module Set
from Microsoft.FSharp.Collections
--------------------
type Set<'T (requires comparison)> =
interface IComparable
interface IEnumerable
interface IEnumerable<'T>
interface ICollection<'T>
new : elements:seq<'T> -> Set<'T>
member Add : value:'T -> Set<'T>
member Contains : value:'T -> bool
override Equals : obj -> bool
member IsProperSubsetOf : otherSet:Set<'T> -> bool
member IsProperSupersetOf : otherSet:Set<'T> -> bool
...
Full name: Microsoft.FSharp.Collections.Set<_>
--------------------
new : elements:seq<'T> -> Set<'T>
union case StateUpdate.SetNop: StateUpdate<'T>
static member StateUpdate.Unit : IMonoid<'T> -> StateUpdate<'a>
Full name: Script.StateResult.StateUpdate`1.Unit
Empty update - do not change the state
static member StateUpdate.Combine : IMonoid<'T> * a:StateUpdate<'a> * b:StateUpdate<'a> -> StateUpdate<'a>
Full name: Script.StateResult.StateUpdate`1.Combine
Combine updates - return the latest (rightmost) 'Set' update
val a : StateUpdate<'a>
val b : StateUpdate<'a>
val v : StateUpdate<'a>
val b : 'a
static member StateUpdate.Apply : IMonoid<'T> * s:StateState<'a> * p:StateUpdate<'a> -> StateState<'a>
Full name: Script.StateResult.StateUpdate`1.Apply
Apply update to a state - the 'Set' update changes the state
val s : StateState<'a>
val p : StateUpdate<'a>
val put : s:'a -> UpdateMonad<'b,StateUpdate<'a>,unit>
Full name: Script.StateResult.put
Put the state to the specified value
val get : UpdateMonad<StateState<'a>,StateUpdate<'b>,'a>
Full name: Script.StateResult.get
Get the current state
val setRun : s:'a -> UpdateMonad<StateState<'a>,'b,'c> -> Result<'b,'c>
Full name: Script.StateResult.setRun
Run a computation using a specified initial state
val f : (StateState<'a> -> Result<'b,'c>)
More information