Skip to content

Instantly share code, notes, and snippets.

@dlidstrom
Last active September 20, 2019 12:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dlidstrom/68cf244ccf3170dab9e612b6df541be4 to your computer and use it in GitHub Desktop.
Save dlidstrom/68cf244ccf3170dab9e612b6df541be4 to your computer and use it in GitHub Desktop.
Mix of result and applicative
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