3 people like it.

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>)
Raw view Test code New version

More information

Link:http://fssnip.net/7Ul
Posted:6 years ago
Author:Fahd Abdeljallal
Tags: monoid , state monad , update monad , reader monad , writer monad