use self::Sig::{
Request,
Respond,
};
pub enum Sig<'a, OU, IU, ID, OD, X> {
Request(OU, Box<FnOnce<(IU,), X> + 'a>),
Respond(OD, Box<FnOnce<(ID,), X> + 'a>),
}
#[inline]
pub fn map<'a, OU, IU, ID, OD, X, Y, F:'a>(
m: Sig<'a, OU, IU, ID, OD, X>,
f: F
) -> Sig<'a, OU, IU, ID, OD, Y>
where
F: FnOnce(X) -> Y,
{
match m {
Request(ou, giu) => Request(ou, box move |:iu| f(giu.call_once((iu,)))),
Respond(od, gid) => Respond(od, box move |:id| f(gid.call_once((id,)))),
}
}
monad!(Proxy, Sig, map, [ OU, IU, ID, OD, ])
pub struct Void;
pub type Effect <'a, R> = Proxy<'a, Void, (), (), Void, R>;
pub type Producer<'a, OD, R> = Proxy<'a, Void, (), (), OD , R>;
pub type Pipe <'a, IU, OD, R> = Proxy<'a, () , IU, (), OD , R>;
pub type Consumer<'a, IU, R> = Proxy<'a, () , IU, (), Void, R>;
pub type Client <'a, OU, IU, R> = Proxy<'a, OU , IU, (), Void, R>;
pub type Server <'a, ID, OD, R> = Proxy<'a, Void, (), ID, OD , R>;
#[inline]
pub fn request<'a, OU, IU, ID, OD>(ou: OU) -> Proxy<'a, OU, IU, ID, OD, IU> {
wrap(Request(ou, box |:iu| box
point(iu)))
}
#[inline]
pub fn respond<'a, OU, IU, ID, OD>(od: OD) -> Proxy<'a, OU, IU, ID, OD, ID> {
wrap(Respond(od, box |:id| box
point(id)))
}
#[inline]
pub fn push<'a, OU, IU, R>(iu: IU) -> Proxy<'a, OU, IU, OU, IU, R> {
wrap(Respond(iu, box |:ou| box
wrap(Request(ou, box |:iu| box
push(iu)))))
}
#[inline]
pub fn pull<'a, OU, IU, R>(ou: OU) -> Proxy<'a, OU, IU, OU, IU, R> {
wrap(Request(ou, box |:iu| box
wrap(Respond(iu, box |:ou| box
pull(ou)))))
}
#[inline]
pub fn closed<A>(_: Void) -> A {
loop {}
}
impl<'a, R:'a> Effect<'a, R> {
#[inline]
pub fn run(self) -> R {
self.go(|&:x| { match x {
Request(v, _) => closed(v),
Respond(v, _) => closed(v),
}})
}
}