Created
August 13, 2011 14:36
-
-
Save forki/1143908 to your computer and use it in GitHub Desktop.
Monad with safe division - idea from http://visualizationtools.net/default/categories-for-dummies/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Of course this can be done with the Maybe monad as seen in https://github.com/panesofglass/FSharp.Monad/blob/master/tests/FSharp.Monad.Tests/MaybeTest.fs