Skip to content

Instantly share code, notes, and snippets.

@forki
Created August 13, 2011 14:36
Show Gist options
  • Select an option

  • Save forki/1143908 to your computer and use it in GitHub Desktop.

Select an option

Save forki/1143908 to your computer and use it in GitHub Desktop.
// 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
let resultF = id
// 2. 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 = resultF x
// 3. Instanciate the monad
let safe = SafeOperationBuilder()
// 4. Define a safe division
let divide x y =
match y with
| 0.0 -> Infinite
| _ -> Value(x/y)
// 5. 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)
}
let result = totalResistance 1.0 2.0 3.0
printfn "%A" result // prints "Value 0.5454..."
let infiniteResult = totalResistance 1.0 0.0 3.0
printfn "%A" infiniteResult // prints "Infinite"
@forki

forki commented Aug 13, 2011

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment