Last active
September 20, 2019 12:11
-
-
Save dlidstrom/68cf244ccf3170dab9e612b6df541be4 to your computer and use it in GitHub Desktop.
Mix of result and applicative
This file contains 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
module Result = | |
let bind f = function | |
| Ok x -> f x | |
| Error x -> Error x | |
let map f = function | |
| Ok x -> Ok(f x) | |
| Error err -> Error err | |
let apply fResult xResult = | |
match fResult, xResult with | |
| Ok f, Ok x -> Ok(f x) | |
| Ok _, Error x -> Error x | |
| Error f, Ok _ -> Error f | |
| Error f, Error x -> Error(f @ x) | |
let (<!>) = Result.map | |
let (<*>) = Result.apply | |
type ResultBuilder() = | |
member this.Bind(m, f) = Result.bind f m | |
member this.Return(x) = Ok x | |
let result = new ResultBuilder() | |
/// mix of monad and applicative | |
type Username = private Username of string | |
with | |
static member create u = | |
if String.length u > 10 | |
then Error ["Too long"] | |
else Ok (Username u) | |
member this.value = match this with Username s -> s | |
type Email = private Email of string | |
with | |
static member create s = | |
if String.length s > 10 | |
then Error ["Wrong email"] | |
else Ok (Email s) | |
member this.value = match this with Email s -> s | |
let login (u : Username) (e : Email) = | |
[|u.value; e.value|] |> String.concat "/" | |
// short circuit any step that returns Error | |
let xx = result { | |
// collects all intermediate results | |
// into one Ok (login successfully called) | |
// or Error (one or more intermediate errors) | |
let! l = | |
login | |
<!> (Username.create "1234567890") | |
<*> (Email.create "1234567890") | |
let! u = Username.create "abc" | |
return u | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment