1use crate::{Bind, Pure};
2use higher::{Lift, Lift3};
3
4pub 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}