Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I haven't got any experience with reactive programming under F#, but the problem of global state in purely functional systems is quite common and has a quite elegant solution: <strong>Monads</strong>.</p> <p>While monads themselves are primarily used in Haskell, the underlying concept made it into F# as <a href="http://en.wikibooks.org/wiki/F_Sharp_Programming/Computation_Expressions" rel="noreferrer">computation expressions</a>.</p> <p>The idea is that you don't actually change states but just describe the transitions of the state, i.e. how to produce new states. The state itself can be completely hidden in the programm. By using special monadic syntax, you can write pure but stateful programms almost imperatively.</p> <p>Taking a (modified) implementation from <a href="http://www.navision-blog.de/2009/10/23/using-monads-in-fsharp-part-i-the-state-monad/" rel="noreferrer">this source</a>, the <code>State</code> monad could look like this</p> <pre><code>let (&gt;&gt;=) x f = (fun s0 -&gt; let a,s = x s0 f a s) let returnS a = (fun s -&gt; a, s) type StateBuilder() = member m.Delay(f) = f() member m.Bind(x, f) = x &gt;&gt;= f member m.Return a = returnS a member m.ReturnFrom(f) = f let state = new StateBuilder() let getState = (fun s -&gt; s, s) let setState s = (fun _ -&gt; (),s) let runState m s = m s |&gt; fst </code></pre> <p>So let's have an example: We want to write a function that can write values into a log (just a list) while proceeding. We therefore define</p> <pre><code>let writeLog x = state { let! oldLog = getState // Notice the ! for monadic computations (i.e. where the state is involved) do! setState (oldLog @ [x]) // Set new state return () // Just return (), we only update the state } </code></pre> <p>Within <code>state</code>, we can now use this in an imperative syntax without having to handle the log list manually.</p> <pre><code>let test = state { let k = 42 do! writeLog k // It's just that - no log list we had to handle explicitly let b = 2 * k do! writeLog b return "Blub" } let (result, finalState) = test [] // Run the stateful computation (starting with an empty list) printfn "Result: %A\nState: %A" result finalState </code></pre> <p>Still, everything is purely functional here ;)</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload