Last active
November 1, 2022 23:16
-
-
Save lucasteles/7bd4e8134bcf69b7c90cbb44b5fb2634 to your computer and use it in GitHub Desktop.
option monad on fsharp
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
open System | |
//Helpers | |
let printOpt opt = | |
match opt with | |
|None -> printfn "None" | |
|Some v -> printfn "Some %s" v | |
// safe functions | |
let exclaimIt str = if str = "" then None else Some (str + "!") | |
let doubleIt str = if str = "" then None else Some (str + str) | |
let upperIt str = if str = "" then None else Some (str |> String.map Char.ToUpper) | |
//normal pipe with bind | |
// if we use Option.map we will get a (string option option), but with bind we get flated result (string option) | |
let pipeOpt = Some "a" | |
|> Option.bind exclaimIt | |
|> Option.bind doubleIt | |
|> Option.bind upperIt | |
printOpt pipeOpt //Some A!A! | |
//is very annoying repeat this pattern everywhere | |
//lets create a Haskell inspired bind operator | |
let (>>=) a b = | |
match a with | |
| None -> None | |
| Some x -> x |> b | |
//so | |
let operatorOpt = | |
Some "a" | |
>>= exclaimIt | |
>>= doubleIt | |
>>= upperIt | |
printOpt operatorOpt //Some A!A! | |
//but... | |
//we have a nested bind problem if needed | |
let chainOpt = | |
"a" |> (fun v -> | |
exclaimIt v >>= (fun x -> | |
doubleIt x >>= (fun y -> | |
upperIt y >>= (fun z -> | |
Some (x + y + z) )))) //return | |
printOpt chainOpt //Some a!a!a!A!A! | |
//awfull! | |
//lets create a computed expression definition for option | |
type MaybeBuilder() = | |
member this.Bind(x, f) = | |
match x with | |
| None -> None | |
| Some a -> f a | |
member this.Return(x) = | |
Some x | |
let maybe = new MaybeBuilder() | |
// then | |
let computed = | |
maybe { | |
let! x = exclaimIt "a" | |
let! y = doubleIt x | |
let! z = upperIt y | |
return x + y + z | |
} | |
printOpt computed //Some a!a!a!A!A! | |
//that's all... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment