#![feature(phase)] #![feature(unboxed_closures)] #[phase(link, plugin)] extern crate monad_macros; extern crate monad; use std::collections::BTreeMap; use monad::monad::reader::trampoline::{ Reader, ask, bind, point, }; use self::Exp::{ Add, Let, Val, Var, }; #[deriving(Clone)] #[deriving(Show)] enum Exp { Add(Box, Box), Let(String, Box, Box), Val(uint), Var(String), } #[allow(dead_code)] fn eval<'a>(e: Exp) -> Reader<'a, BTreeMap, Option> { match e { Add(box e1, box e2) => { mdo! { o1: Option <- eval(e1); o2: Option <- eval(e2); let res = o1.and_then(|v1| o2.and_then(|v2| Some(v1 + v2) )); end point(res) } }, Let(x, box e1, box e2) => { mdo! { o1: Option <- eval(e1); end eval(e2).local(move |:mut ctx: BTreeMap| { o1.map(|v1| (&mut ctx).insert(x.clone(), v1)); ctx }) } }, Val(n) => point(Some(n)), Var(x) => { mdo! { ctx: BTreeMap <- ask(); end point(ctx.get(&x).map(|x| *x)) } }, } } #[allow(dead_code)] fn main() { fn exp_test(var: &str) -> Exp { Let(String::from_str("x"), box Val(42u), box Add( box Let(String::from_str("y"), box Val(43u), box Add( box Var(String::from_str("x")), box Var(String::from_str("y")) ) ), box Var(String::from_str(var)) ) ) } println!("{}", eval(exp_test("x")).run(BTreeMap::new())); println!("{}", eval(exp_test("y")).run(BTreeMap::new())); }