State Monad - While-loops
f#, guard-clause, monads, state-monad
Solution
If you look at the different computation builders in ExtCore, there is one interesting thing to note - for any monad, the implementation of `While` (and also `For`) member is usually the same.
This is because you can always express the operation in terms of `Bind`, `Zero` and recursive uses of `While`. So if you are working with monads, you will always define something like this (Just replace `M<_>` with your monad):
// (unit -> bool) * M<'T> -> M<'T>
member this.While (guard, body : M<_>) : M<_> =
if guard () then
this.Bind (body, (fun () -> this.While (guard, body)))
else
this.Zero ()
This is not true for all computations - if the computation is more interesting in some way, then it may need a different implementation of `While`, but the above is a reasonable default.
Aside - I think that the need to define custom computation expressions in F# should be quite rare - idiomatic F# code does not use monads nearly as often as e.g. Haskell and most of the time, you should be fine with what the standard library has (or what ExtCore defines, if you are doing something more advanced). Perhaps you need a custom computation, but keep in mind that this might be a distraction leading you in a wrong direction...
Problem
This question has been inspired by this question. I understand the example (`ListBuilder`) but I have not been able to create a `while` loop for my state monad. What is not clear to me is how to `bind` the body of the `while`loop as the iterations follow one an another. Thank you. ``` ///////////////////////////////////////////////////////////////////////////////////// // Definition of the state ///////////////////////////////////////////////////////////////////////////////////// type StateFunc<'State, 'T> = 'State -> 'T * 'State ///////////////////////////////////////////////////////////////////////////////////// // Definition of the State monad ///////////////////////////////////////////////////////////////////////////////////// type StateMonadBuilder<'State>() = // M<'T> -> M<'T> member b.ReturnFrom a : StateFunc<'State, 'T> = a // 'T -> M<'T> member b.Return a : StateFunc<'State, 'T> = ( fun s -> a, s) // M<'T> * ('T -> M<'U>) -> M<'U> member b.Bind(p : StateFunc<_, 'T>, rest : 'T -> StateFunc<_,_>) : StateFunc<'State, 'U> = (fun s -> let a, s' = p s rest a s') member b.Zero() = fun s -> (), s member b.Delay f = f member b.Run f = f () // Getter for the whole state, this type signature is because it passes along the state & returns the state member b.getState : StateFunc<'State, _> = (fun s -> s, s) // Setter for the state member b.putState (s:'State) : StateFunc<'State, _> = (fun _ -> (), s) // (unit -> bool) * M<'T> -> M<'T> member b.While (cond, body: StateFunc<'State, _>): StateFunc<'State, _> = (fun s -> if cond () then let bind = let _, s' = body s fun s' -> body s' b.While (cond, bind) // This is wrong else body s) ```