Skip to content

Instantly share code, notes, and snippets.

@zobar
Created October 15, 2017 23:55
Show Gist options
  • Save zobar/d4b7cd01037cf560443ed319c9c577a2 to your computer and use it in GitHub Desktop.
Save zobar/d4b7cd01037cf560443ed319c9c577a2 to your computer and use it in GitHub Desktop.
trait Reader<A>
where
Self: Sized,
{
type Out;
fn apply(&self, a: &A) -> Self::Out;
fn map<'a, G>(&'a self, g: &'a G) -> Map<Self, G> {
Map(self, g)
}
fn zip<'a, G>(&'a self, g: &'a G) -> Zip<Self, G> {
Zip(self, g)
}
fn and_then<'a, G>(&'a self, g: &'a G) -> AndThen<Self, G> {
AndThen(self, g)
}
}
impl<A, B, F> Reader<A> for F
where
F: Fn(&A) -> B,
{
type Out = B;
fn apply(&self, a: &A) -> B {
self(a)
}
}
struct Map<'a, F: 'a, G: 'a>(&'a F, &'a G);
impl<'a, A, F, G> Reader<A> for Map<'a, F, G>
where
F: Reader<A>,
G: Reader<F::Out>,
{
type Out = G::Out;
fn apply(&self, a: &A) -> G::Out {
self.1.apply(&self.0.apply(a))
}
}
struct Zip<'a, F: 'a, G: 'a>(&'a F, &'a G);
impl<'a, A, F, G> Reader<A> for Zip<'a, F, G>
where
F: Reader<A>,
G: Reader<A>,
{
type Out = (F::Out, G::Out);
fn apply(&self, a: &A) -> (F::Out, G::Out) {
(self.0.apply(a), self.1.apply(a))
}
}
struct AndThen<'a, F: 'a, G: 'a>(&'a F, &'a G);
impl<'a, A, F, G, H> Reader<A> for AndThen<'a, F, G>
where
F: Reader<A>,
G: Reader<F::Out, Out = H>,
H: Reader<A>,
{
type Out = H::Out;
fn apply(&self, a: &A) -> H::Out {
self.1.apply(&self.0.apply(a)).apply(a)
}
}
fn main() {
let id = |i: &i64| *i;
let inc = |i: &i64| i + 1;
let mul = |i: &i64| move |j: &i64| i * j;
let x = id.zip(&inc.and_then(&mul)).apply(&3);
println!("Got {:?}", x)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment