Last active
February 8, 2017 18:20
-
-
Save kyleheadley/3b0010af2a05692cbb68f0d1f3e1b108 to your computer and use it in GitHub Desktop.
Prototype implementation of Monads in Rust
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
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