//@NO-IMPLICIT-PRELUDE
//! Composable effect types
let { error } = import! std.prim
let option = import! std.option
let { Result, ? } = import! std.result
let { (<<), (|>) } = import! std.function
let { (<>) } = import! std.semigroup
let monoid @ { Monoid } = import! std.monoid
let { Functor, map } = import! std.functor
let { Applicative, wrap } = import! std.applicative
let { Monad } = import! std.monad
rec
/// An effectful function `a -> b`
type Arr r a b = a -> Eff r b
/// The `Eff` monad provides composable effect via a `Row` of effects (`r`) and produces a value of type `a`.
type Eff r a =
| Pure a
| Impure : forall x . r x -> Arr r x a -> Eff r a
in
let compose f g : Arr r a b -> Arr r b c -> Arr r a c = \a ->
match f a with
| Pure b -> g b
| Impure r h -> Impure r (compose h g)
let wrap_eff x : a -> Eff r a = Pure x
let flat_map_eff f m : (a -> Eff r b) -> Eff r a -> Eff r b =
match m with
| Pure x -> f x
| Impure row g -> Impure row (compose g f)
let functor : Functor (Eff r) = {
map = \f m -> flat_map_eff (\x -> wrap_eff (f x)) m,
}
let applicative : Applicative (Eff r) = {
functor,
apply = \f g -> flat_map_eff (\f1 -> flat_map_eff (\g1 -> wrap_eff (f1 g1)) g) f,
wrap = wrap_eff,
}
let monad : Monad (Eff r) = {
applicative,
flat_map = flat_map_eff,
}
type OpenVariant r a = .. r
#[doc(hidden)]
let inject_rest x : forall e . OpenVariant r a -> [| | r |] a = convert_effect! x
/// Extracts the value of type `a` from an effectful computation. Can only be done once all other
/// effects have been eliminated from the row (leaving `[| |]` as the empty effect). See each
/// individual effects module on how to eliminate the effect.
let run_pure eff : Eff [| |] a -> a =
match eff with
| Pure v -> v
| Impure _ _ -> error "Impossible: run_pure"
{
Eff,
Arr,
functor,
applicative,
monad,
run_pure,
inject_rest,
}