Skip to content

Instantly share code, notes, and snippets.

View forki's full-sized avatar

Steffen Forkmann forki

View GitHub Profile
// 1. Define the monad
type 'a Result =
| Value of 'a
| Infinite
let bindF r (f: 'a -> 'a Result) =
match r with
| Value x -> f x
| Infinite -> Infinite
type 'a History = {
Current:'a
Undos : 'a list
Redos : 'a list }
let empty x = { Current = x; Undos = []; Redos = [] }
let current history = history.Current
type State<'a, 's> = 's -> 'a * 's
@forki
forki / gist:1146878
Created August 15, 2011 14:36
A simple monad which encapsulates Infinity
// Define the monad
type 'a Result =
| Value of 'a
| Infinite
let bindF r (f: 'a -> 'a Result) =
match r with
| Value x -> f x
| Infinite -> Infinite
@forki
forki / gist:1146903
Created August 15, 2011 14:49
Define the builder in order to allow syntactic sugar
// use a computation expression builder
// in order to allow syntactic sugar
type SafeOperationBuilder() =
member this.Bind (r, f) = bindF r f
member this.Return x = returnF x
// instanciate the monad
let safe = SafeOperationBuilder()
@forki
forki / gist:1146914
Created August 15, 2011 14:54
A safe division
// Define a safe division
// which treats "division by zero" as infinity
let divide x y =
match y with
| 0.0 -> Infinite
| _ -> Value(x/y)
@forki
forki / gist:1146922
Created August 15, 2011 14:56
A sample computation inside the InfinityMonad
// Use the safe division in a computation expression
let totalResistance r1 r2 r3 =
safe {
// no DivideByZero exception occurs here
let! x = divide 1.0 r1
let! y = divide 1.0 r2
let! z = divide 1.0 r3
return divide 1.0 (x + y + z)
}
@forki
forki / gist:1147108
Created August 15, 2011 16:24
Using the Undo-Monad in a simple text editor
let simpleTextEditorSample = undoable {
let! _ = add "bla"
let! _ = add "blub"
let! _ = add "foo"
let! _ = undo
let! _ = undo
let! _ = redo
let! _ = add "bar"
return () }
@forki
forki / gist:1147146
Created August 15, 2011 16:36
Define the Undo-Monad in terms of the StateMonad
// Define the Undo-Monad on top of StateMonad
let undoable = new StateBuilder()
type 'a History = {
Current:'a
Undos : 'a list
Redos : 'a list }
let empty x = { Current = x; Undos = []; Redos = [] }
@forki
forki / gist:1147157
Created August 15, 2011 16:40
Helper functions which allow to access and manipulate the history in an UndoMonad
let putToHistory x = undoable {
let! history = getState
do! putState
{ Current = x;
Undos = history.Current :: history.Undos
Redos = [] } }
let exec m s = (m s |> snd).Current
let getCurrent<'a> = undoable {
@forki
forki / gist:1147341
Created August 15, 2011 18:14
A small query using the DistributionMonad
let fairCoinAndDice = distribution {
let! d = fairDice 6
let! c = fairCoin
return d,c }
fairCoinAndDice
|> filter (fun (d,c) -> c = Heads && d > 3)
|> probability
|> printfn "P(Heads and dice > 3) = %A" // "1/4N"