Prototype implementation of Monads in Rust
use std::fmt::Display; | |
trait Monadic {} | |
#[derive(Debug)] | |
struct Monad<M:Monadic,T>(M,T); | |
#[derive(Debug)] | |
struct Opt(bool); | |
impl Monadic for Opt {} | |
impl<T:Default> Monad<Opt,T> { | |
fn ret(t:T) -> Self { | |
Monad(Opt(true),t) | |
} | |
fn bind<F,U:Default>(self,f:F) -> Monad<Opt,U> where | |
F: FnOnce(T) -> Monad<Opt,U> | |
{ | |
let Monad(Opt(is_some),val) = self; | |
if is_some { f(val) } else { Monad(Opt(false),Default::default()) } | |
} | |
fn none() -> Self { Monad(Opt(false),Default::default())} | |
} | |
#[derive(Debug)] | |
struct Log(String); | |
impl Monadic for Log {} | |
impl<T:Display> Monad<Log,T> { | |
fn ret(t:T) -> Self { | |
Monad(Log(format!("{}",t)),t) | |
} | |
fn bind<F,U>(self,f:F) -> Monad<Log,U> where | |
F: FnOnce(T) -> Monad<Log,U> | |
{ | |
let Monad(Log(old_log),val) = self; | |
let Monad(Log(new_log),val) = f(val); | |
Monad(Log(format!("{},{}",old_log,new_log)),val) | |
} | |
} | |
fn main() { | |
let just3 = Monad::<Opt,_>::ret(3); | |
println!("{:?}",just3); | |
let just4 = just3.bind(|x|Monad::<Opt,_>::ret(x+1)); | |
println!("{:?}",just4); | |
let nope = Monad::<Opt,usize>::none(); | |
let nope2 = nope.bind(|x|Monad::<Opt,_>::ret(x+1)); | |
println!("{:?}",nope2); | |
let nope3 = just4.bind(|_|Monad::<_,usize>::none()); | |
println!("{:?}",nope3); | |
let nope = Monad::<Opt,usize>::none(); | |
let nope4 = nope.bind(|x|Monad::<Opt,_>::ret(format!("{}",x))); | |
println!("{:?}",nope4); | |
let just5 = Monad::<Opt,_>::ret(5); | |
let str5 = just5.bind(|x|Monad::<Opt,_>::ret(format!("{}",x))); | |
println!("{:?}",str5); | |
let logone = Monad::<Log,_>::ret(1); | |
let logtwo = logone.bind(|x|Monad::<Log,_>::ret(x+1)); | |
let loghuh = logtwo.bind(|_|Monad::<Log,_>::ret("huh")); | |
let logpi = loghuh.bind(|_|Monad::<Log,_>::ret(3.14159)); | |
let logtau = logpi.bind(|p|Monad::<Log,_>::ret(p*2.0)); | |
let logdub = logtau.bind(|_|Monad::<Log,_>::ret("once").bind(|_|Monad::<Log,_>::ret("twice"))); | |
print!("{:?}", logdub); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment