Last active
July 5, 2021 11:56
-
-
Save Szer/d14fc836a5c305af736a121278bc8df4 to your computer and use it in GitHub Desktop.
This is a joke
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
type Effect<'env, 'out> = Effect of ('env -> 'out) | |
module Effect = | |
let value x = Effect (fun _ -> x) | |
let apply f = Effect f | |
let run env (Effect f) = f env | |
let run' (Effect f) env = f env | |
let map f (Effect g) = Effect(f << g) | |
let local f (Effect g) = Effect(f >> g) | |
let inline bind f effect = | |
Effect (fun env -> | |
let x = run env effect | |
run env (f x) | |
) | |
let map2 f x y = | |
Effect(fun env -> | |
let x = run env x | |
let y = run env y | |
f x y | |
) | |
let inline (^) f x = f x | |
let inline (>>-) x f = Effect.map f x | |
let inline (!>) x = Effect.value x | |
let inline (!>>) x = Effect.apply x | |
type ResultBuilder() = | |
member __.Return value = Result.Ok value | |
member __.ReturnFrom (result: Result<_,_>) = result | |
member __.Bind(result, fn) = Result.bind fn result | |
type EffectBuilder() = | |
member __.Return value = !> value | |
member __.Zero () = !> Unchecked.defaultof<_> | |
member __.ReturnFrom (effect: Effect<'env, 'out>) = effect | |
member __.Bind(effect, fn) = Effect.bind fn effect | |
let effect = EffectBuilder() | |
let result = ResultBuilder() | |
module Async = | |
let map f x = async.Bind(x, f >> async.Return) | |
let map2 f x y = async { | |
let! x = x | |
let! y = y | |
return f x y | |
} | |
module Result = | |
let traverseAsync: Result<Async<'a>,'b> -> Async<Result<'a,'b>> = function | |
| Result.Ok async -> Async.map Result.Ok async | |
| Error exn -> async.Return (Result.Error exn) | |
let traverseEffect = function | |
| Result.Ok effect -> Effect.map Result.Ok effect | |
| Error exn -> !> (Result.Error exn) | |
let flatten = function | |
| Result.Ok r -> r | |
| Error exn -> Error exn | |
let map2 f x y = result { | |
let! x = x | |
let! y = y | |
return f x y | |
} | |
type ReceiveRequest = class end | |
type ValidatedRequest = class end | |
type CanonicalizeEmail = class end | |
let receiveRequest: ReceiveRequest = failwith "" | |
let validateRequest: ReceiveRequest -> Result<ValidatedRequest, exn> = failwith "" | |
let canonicalizeEmail: ValidatedRequest -> Result<CanonicalizeEmail, exn> = failwith "" | |
let updateDbDromRequest: CanonicalizeEmail -> Async<Result<unit, exn>> = failwith "" | |
let sendEmail: ValidatedRequest -> Async<Result<unit, exn>> = failwith "" | |
let effectfulSendEmail: Effect<ValidatedRequest, Async<Result<unit, exn>>> = | |
!>> sendEmail | |
let effectfulCanonicalizeEmail: Effect<ValidatedRequest, Async<Result<unit, exn>>> = | |
!>> canonicalizeEmail | |
>>- Result.map updateDbDromRequest | |
>>- Result.traverseAsync | |
>>- Async.map Result.flatten | |
let combinedFlow: Effect<ValidatedRequest, Async<Result<unit, exn>>> = | |
(effectfulCanonicalizeEmail, effectfulSendEmail) | |
||> Effect.map2 ^Async.map2 ^Result.map2 ^fun () () -> () | |
let updateCustomerFlow: Effect<ReceiveRequest, Async<Result<unit, exn>>> = | |
!>> validateRequest | |
>>- Result.map ^Effect.run' combinedFlow | |
>>- Result.traverseAsync | |
>>- Async.map Result.flatten | |
let updateCustomer: ReceiveRequest -> Async<Result<unit, exn>> = | |
Effect.run' updateCustomerFlow |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment