Struct higher_effect::IO
source · pub struct IO<'a, A, E> { /* private fields */ }
Expand description
An IO monad.
This wraps a Future
similarly to the Effect
monad, but the wrapped effect must return a Result
. Just as with
Result
’s Bind
implementation, this also short circuits
a chain of computations if a step produces an error, resolving immediately
to that error.
You can construct an IO monad from a Future
which returns a
Result
:
let my_io_monad = IO::<&str, &str>::from(async { Ok("Hello Joe!") });
You can .await
an IO monad and get a Result
back:
assert_eq!(my_io_monad.await, Ok("Hello Joe!"));
You can run your IO monads on a thread local executor using the
run()
method. Naturally, we also provide a version of Haskell’s
putStrLn
so that we can implement the canonical hello world in monadic Rust:
put_str_ln("Hello Simon!").run();
Because IO implements Bind
, you can chain async IO
operations together using the run!
macro:
run! {
put_str("What is your name? ");
name <= get_line();
put_str_ln(format!("Hello {}!", name))
}.run();
Implementations§
source§impl<'a, A, E> IO<'a, A, E>
impl<'a, A, E> IO<'a, A, E>
sourcepub fn map_ok<B, F>(self, f: F) -> IO<'a, B, E>where
A: 'a,
B: 'a,
E: 'a,
F: FnOnce(A) -> B + 'a,
pub fn map_ok<B, F>(self, f: F) -> IO<'a, B, E>where
A: 'a,
B: 'a,
E: 'a,
F: FnOnce(A) -> B + 'a,
Transform the effect’s success value using the given function.
If the effect fails, the function is not applied.
This is identical to Functor::fmap
, except it accepts
a FnOnce
instead of a Fn
.
sourcepub fn map_error<B, F>(self, f: F) -> IO<'a, A, B>where
A: 'a,
B: 'a,
E: 'a,
F: FnOnce(E) -> B + 'a,
pub fn map_error<B, F>(self, f: F) -> IO<'a, A, B>where
A: 'a,
B: 'a,
E: 'a,
F: FnOnce(E) -> B + 'a,
Transform the effect’s error value using the given function.
If the effect succeeds, the function is not applied.
This is identical to Bifunctor::rmap
, except it accepts
a FnOnce
instead of a Fn
.
sourcepub fn try_select<B, EB>(
eff1: IO<'a, A, E>,
eff2: IO<'a, B, EB>
) -> IO<'a, Either<(A, IO<'a, B, EB>), (B, IO<'a, A, E>)>, Either<(E, IO<'a, B, EB>), (EB, IO<'a, A, E>)>>where
A: 'a,
B: 'a,
E: 'a,
EB: 'a,
pub fn try_select<B, EB>(
eff1: IO<'a, A, E>,
eff2: IO<'a, B, EB>
) -> IO<'a, Either<(A, IO<'a, B, EB>), (B, IO<'a, A, E>)>, Either<(E, IO<'a, B, EB>), (EB, IO<'a, A, E>)>>where
A: 'a,
B: 'a,
E: 'a,
EB: 'a,
Run two effects in parallel, returning the result of whichever finishes first, or the error from whichever fails first.
sourcepub fn select_ok<I>(iter: I) -> IO<'a, (A, Vec<IO<'a, A, E>>), E>where
A: 'a,
E: 'a,
I: IntoIterator<Item = IO<'a, A, E>> + 'a,
pub fn select_ok<I>(iter: I) -> IO<'a, (A, Vec<IO<'a, A, E>>), E>where
A: 'a,
E: 'a,
I: IntoIterator<Item = IO<'a, A, E>> + 'a,
Run a list of effects in parallel, returning the result of whichever finishes first, or the first error to occur.
sourcepub fn try_join<B>(eff1: IO<'a, A, E>, eff2: IO<'a, B, E>) -> IO<'a, (A, B), E>where
A: 'a,
B: 'a,
E: 'a,
pub fn try_join<B>(eff1: IO<'a, A, E>, eff2: IO<'a, B, E>) -> IO<'a, (A, B), E>where
A: 'a,
B: 'a,
E: 'a,
Run two effects in parallel, returning the results of both, or the error from whichever fails first.
sourcepub fn try_join3<B, C>(
eff1: IO<'a, A, E>,
eff2: IO<'a, B, E>,
eff3: IO<'a, C, E>
) -> IO<'a, (A, B, C), E>where
A: 'a,
B: 'a,
C: 'a,
E: 'a,
pub fn try_join3<B, C>(
eff1: IO<'a, A, E>,
eff2: IO<'a, B, E>,
eff3: IO<'a, C, E>
) -> IO<'a, (A, B, C), E>where
A: 'a,
B: 'a,
C: 'a,
E: 'a,
Run three effects in parallel, returning the results of all three, or the error from whichever fails first.
sourcepub fn try_join4<B, C, D>(
eff1: IO<'a, A, E>,
eff2: IO<'a, B, E>,
eff3: IO<'a, C, E>,
eff4: IO<'a, D, E>
) -> IO<'a, (A, B, C, D), E>where
A: 'a,
B: 'a,
C: 'a,
D: 'a,
E: 'a,
pub fn try_join4<B, C, D>(
eff1: IO<'a, A, E>,
eff2: IO<'a, B, E>,
eff3: IO<'a, C, E>,
eff4: IO<'a, D, E>
) -> IO<'a, (A, B, C, D), E>where
A: 'a,
B: 'a,
C: 'a,
D: 'a,
E: 'a,
Run four effects in parallel, returning the results of all four, or the error from whichever fails first.
sourcepub fn try_join_all<I>(iter: I) -> IO<'a, Vec<A>, E>where
I: IntoIterator<Item = IO<'a, A, E>> + 'a,
pub fn try_join_all<I>(iter: I) -> IO<'a, Vec<A>, E>where
I: IntoIterator<Item = IO<'a, A, E>> + 'a,
Run a list of effects in parallel, returning a list of their results, or the error from whichever fails first.
Trait Implementations§
source§impl<'a, A: 'a, E: 'a> ApplicativeError<'a, A, E> for IO<'a, A, E>
impl<'a, A: 'a, E: 'a> ApplicativeError<'a, A, E> for IO<'a, A, E>
source§fn throw_error(error: E) -> Self
fn throw_error(error: E) -> Self
source§fn handle_error_with<F>(self, f: F) -> Selfwhere
F: Fn(E) -> Self + 'a,
fn handle_error_with<F>(self, f: F) -> Selfwhere
F: Fn(E) -> Self + 'a,
source§fn handle_error<F>(self, f: F) -> Selfwhere
F: 'a + Fn(E) -> A,
Self: Sized,
fn handle_error<F>(self, f: F) -> Selfwhere
F: 'a + Fn(E) -> A,
Self: Sized,
fn recover_with<F>(self, recover: F) -> Selfwhere
Self: Sized,
F: Fn(E) -> Result<Self, E> + 'a,
fn recover<F>(self, recover: F) -> Selfwhere
Self: Sized,
F: Fn(E) -> Result<A, E> + 'a,
fn adapt_error<F>(self, adapt: F) -> Selfwhere
Self: Sized,
F: Fn(E) -> E + 'a,
fn redeem<B, FE, FA>(self, recover: FE, map: FA) -> Self::Target<B>where
B: 'a,
FE: 'a + Fn(E) -> B,
FA: 'a + Fn(A) -> B,
Self: Sized,
Self::Target<B>: ApplicativeError<'a, B, E>,
fn from_option<F>(option: Option<A>, if_error: F) -> Selfwhere
Self: Sized,
F: FnOnce() -> E,
fn from_result(result: Result<A, E>) -> Selfwhere
Self: Sized,
source§impl<'a, A, E: 'a> Apply<'a, A> for IO<'a, A, E>where
A: Clone + 'a,
impl<'a, A, E: 'a> Apply<'a, A> for IO<'a, A, E>where
A: Clone + 'a,
source§fn apply<B>(self, f: Self::Target<ApplyFn<'a, A, B>>) -> Self::Target<B>where
B: 'a,
fn apply<B>(self, f: Self::Target<ApplyFn<'a, A, B>>) -> Self::Target<B>where
B: 'a,
F
of functions from A
to B
to an F
of A
,
producing an F
of B
.fn apply_first<B>(self, b: Self::Target<B>) -> Selfwhere
B: 'a,
Self: Sized,
A: Clone,
Self::Target<B>: Apply<'a, B, Target<ApplyFn<'a, B, A>> = Self::Target<ApplyFn<'a, B, A>>>,
fn apply_second<B>(self, b: Self::Target<B>) -> Self::Target<B>where
B: 'a + Clone,
Self: Sized,
Self::Target<B>: Apply<'a, B, Target<ApplyFn<'a, A, B>> = Self::Target<ApplyFn<'a, A, B>>>,
source§impl<'a, A: 'a, E: 'a> Bifunctor<'a, A, E> for IO<'a, A, E>
impl<'a, A: 'a, E: 'a> Bifunctor<'a, A, E> for IO<'a, A, E>
type Target<T, U>
where
T: 'a,
U: 'a = IO<'a, T, U>
source§fn bimap<A2, E2, L, R>(self, left: L, right: R) -> Self::Target<A2, E2>where
A2: 'a,
E2: 'a,
L: Fn(A) -> A2 + 'a,
R: Fn(E) -> E2 + 'a,
fn bimap<A2, E2, L, R>(self, left: L, right: R) -> Self::Target<A2, E2>where
A2: 'a,
E2: 'a,
L: Fn(A) -> A2 + 'a,
R: Fn(E) -> E2 + 'a,
Bifunctor<A, B>
to a Bifunctor<C, D>
using a function from A
to C
and a function from B
to D
.source§impl<'a, A: 'a, E: 'a> Functor<'a, A> for IO<'a, A, E>
impl<'a, A: 'a, E: 'a> Functor<'a, A> for IO<'a, A, E>
type Target<T>
where
T: 'a = IO<'a, T, E>
source§fn fmap<B, F>(self, f: F) -> Self::Target<B>where
B: 'a,
F: Fn(A) -> B + 'a,
fn fmap<B, F>(self, f: F) -> Self::Target<B>where
B: 'a,
F: Fn(A) -> B + 'a,
A
to a functor of B
using a function from A
to B
.