Created
July 5, 2015 21:18
-
-
Save anonymous/521235f3f3cd5b4336ce to your computer and use it in GitHub Desktop.
Shared via Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(fnbox)] | |
use std::ops::Mul; | |
pub mod hkt { | |
pub trait HktAt<T> { | |
type Out: HasHkt<Hkt=Self, Arg=T>; | |
} | |
pub trait HasHkt { | |
type Arg; | |
type Hkt: HktAt<Self::Arg, Out=Self>; | |
} | |
pub type Apply<Hkt, T> where Hkt: HktAt<T> = Hkt::Out; | |
pub trait Monad: HasHkt + Sized { | |
fn bind<U, F>(self, f: F) -> Apply<Self::Hkt, U> | |
where F: FnOnce(Self::Arg) -> Apply<Self::Hkt, U>, | |
Apply<Self::Hkt, U>: Monad; | |
fn ret(x: Self::Arg) -> Self; | |
fn join(self) -> Self::Arg | |
where <Self as HasHkt>::Arg: HasHkt<Hkt=Self::Hkt> + Monad, | |
<Self as HasHkt>::Hkt: HktAt<<Self::Arg as HasHkt>::Arg, Out=Self::Arg> { | |
self.bind(|x| x) | |
} | |
fn then<U>(self, other: Apply<Self::Hkt, U>) -> Apply<Self::Hkt, U> | |
where | |
Self::Hkt: HktAt<U>, | |
Apply<Self::Hkt, U>: Monad { | |
self.bind::<U, _>(move |_| other) | |
} | |
} | |
} | |
use hkt::*; | |
pub mod func { | |
use std::marker::PhantomData; | |
use std::boxed::FnBox; | |
use ::hkt::*; | |
pub struct Func_<'a, R> { | |
phantom: PhantomData<Fn(R) + 'a>, | |
} | |
pub struct Func<'a, R, T> { | |
func: Box<FnBox(R) -> T + 'a>, | |
} | |
impl<'a, R, T> Func<'a, R, T> { | |
pub fn new<F>(f: F) -> Func<'a, R, T> where F: FnOnce(R) -> T + 'a { | |
Func{func: Box::new(f)} | |
} | |
pub fn call(self, r: R) -> T { (self.func)(r) } | |
} | |
impl<'a, T, R> HktAt<T> for Func_<'a, R> { | |
type Out = Func<'a, R, T>; | |
} | |
impl<'a, R, T> HasHkt for Func<'a, R, T> { | |
type Arg = T; | |
type Hkt = Func_<'a, R>; | |
} | |
impl<'a, R, T> Monad for Func<'a, R, T> | |
where R: Clone + 'a, T: 'a { | |
fn bind<U, F>(self, f: F) -> Func<'a, R, U> | |
where F: FnOnce(T) -> Func<'a, R, U> + 'a { | |
Func::new(move |r: R| f(self.call(r.clone())).call(r)) | |
} | |
fn ret(x: T) -> Func<'a, R, T> { Func::new(move |_| x) } | |
} | |
} | |
use func::*; | |
pub mod state { | |
use std::marker::PhantomData; | |
use std::boxed::FnBox; | |
use ::hkt::*; | |
pub struct State_<'a, S> { | |
phantom: PhantomData<Fn(S) -> S + 'a>, | |
} | |
pub struct State<'a, S, T> { | |
func: Box<FnBox(S) -> (S, T) + 'a>, | |
} | |
impl<'a, S, T> State<'a, S, T> { | |
pub fn new<F>(f: F) -> State<'a, S, T> where F: FnOnce(S) -> (S, T) + 'a { | |
State{func: Box::new(f)} | |
} | |
pub fn call(self, r: S) -> (S, T) { (self.func)(r) } | |
} | |
impl<'a, S, T> HktAt<T> for State_<'a, S> { | |
type Out = State<'a, S, T>; | |
} | |
impl<'a, S, T> HasHkt for State<'a, S, T> { | |
type Arg = T; | |
type Hkt = State_<'a, S>; | |
} | |
impl<'a, S, T> Monad for State<'a, S, T> | |
where S: Clone + 'a, T: Clone + 'a { | |
fn bind<U, F>(self, f: F) -> State<'a, S, U> | |
where F: FnOnce(T) -> State<'a, S, U> + 'a { | |
State::new(move |s1: S| { | |
let (s2, t) = self.call(s1); | |
f(t).call(s2) | |
}) | |
} | |
fn ret(x: T) -> State<'a, S, T> { | |
State::new(move |s| (s, x)) | |
} | |
} | |
pub fn put<'a, T: Clone + 'a>(t: T) -> State<'a, T, T> { | |
State::new(move |_| (t.clone(), t)) | |
} | |
pub fn get<'a, S: Clone + 'a>() -> State<'a, S, S> { | |
State::new(move |s: S| (s.clone(), s)) | |
} | |
} | |
use state::*; | |
fn mul_state<'a, S, T>(t: T) -> State<'a, S, T> | |
where S: for<'b> Mul<&'b T, Output=S> + Clone + 'a, | |
T: Clone + 'a, { | |
let t2 = t.clone(); | |
get().bind(move |x| put(x*&t)).then(State::ret(t2)) | |
} | |
fn main() { | |
println!("{}", | |
Func::ret(Func::ret(2)).join().then(Func::ret(4)).call(0) | |
); | |
println!("{:?}", | |
State::ret(2) | |
.bind(mul_state) | |
.then(State::ret(4)) | |
.bind(mul_state) | |
.call(3) | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment