higher_cat/
ap.rs

1use crate::{Bind, Pure};
2use higher::{Lift, Lift3};
3
4/// `Ap` provides an implementation for `Apply::apply` using only `Bind` and
5/// `Pure`.
6pub trait Ap<A, F, B>: Lift3<A, F, B> + Bind<A, B>
7where
8    A: Clone,
9    <Self as Lift3<A, F, B>>::Target2: Bind<F, B> + Clone,
10    <<Self as Lift3<A, F, B>>::Target2 as Lift<F, B>>::Target1: Pure<B>,
11    F: Fn(A) -> B,
12{
13    fn ap(self, f: <Self as Lift3<A, F, B>>::Target2) -> <Self as Lift<A, B>>::Target1;
14}
15
16impl<M, A, F, B> Ap<A, F, B> for M
17where
18    M: Lift3<A, F, B> + Bind<A, B>,
19    A: Clone,
20    <M as Lift3<A, F, B>>::Target2: Bind<F, B> + Clone,
21    <<M as Lift3<A, F, B>>::Target2 as Lift<F, B>>::Target1: Pure<B>,
22    F: Fn(A) -> B,
23{
24    fn ap(self, f: <Self as Lift3<A, F, B>>::Target2) -> <Self as Lift<A, B>>::Target1 {
25        self.bind(|v: A| {
26            let m: <<Self as Lift3<A, F, B>>::Target2 as Lift<F, B>>::Target1 =
27                f.clone().bind(|fun: F| Pure::pure(fun(v.clone())));
28            Self::cast(m)
29        })
30    }
31}