From b14b3a4f29a5342ddeaed1ed575436789c142ba6 Mon Sep 17 00:00:00 2001 From: Andreas Larsen Date: Tue, 6 Sep 2022 19:14:00 +0200 Subject: [PATCH] init --- .gitignore | 1 + Cargo.lock | 7 +++ Cargo.toml | 8 ++++ src/main.rs | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e66d2d0 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "statemonad" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d82a6f3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "statemonad" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7bffcae --- /dev/null +++ b/src/main.rs @@ -0,0 +1,129 @@ +mod state { + // State monad + pub struct WithState<'c, Value, State>(Box (Value, State) + 'c>); + + impl <'c, Value, State> WithState<'c, Value, State> { + pub fn of(f: impl FnOnce(State) -> (Value, State) + 'c) -> WithState<'c, Value, State> { + WithState(Box::new(f)) + } + + pub fn run(self, s: State) -> (Value, State) { + self.0(s) + } + + pub fn bind<'cn, NewValue>(self, f: impl FnOnce(Value) -> WithState<'cn, NewValue, State> + 'cn) -> WithState<'cn, NewValue, State> + where 'c: 'cn, State : 'cn, Value : 'cn { + WithState::<'cn, NewValue, State>::of(move |n| { + let (x,sp) = self.run(n); + f(x).run(sp) + }) + } + + pub fn zip<'cn, NewValue>(self, st: WithState<'cn, NewValue, State>) -> WithState<'cn, (Value,NewValue), State> + where 'c: 'cn, State: 'cn, Value: 'cn, NewValue: 'cn { + self.bind(|aa| st.map(|bb| (aa,bb))) + } + + pub fn map<'cn, NewValue>(self, f: impl FnOnce(Value) -> NewValue + 'cn) -> WithState<'cn, NewValue, State> + where 'c: 'cn, State : 'cn, Value : 'cn { + WithState::<'cn, NewValue, State>::of(move |n| { + let (x, sp) = self.run(n); + ( f(x), sp ) + }) + } + } +} + + +mod labelgenerators { + use super::state::WithState; + + // Generate a next label + pub trait States { + type Item; + fn init() -> Self::Item; + fn next<'c, Value>(f: impl FnOnce(Self::Item) -> Value + 'c) -> WithState<'c, Value, Self::Item>; + } + + pub struct IntCounter; + + impl States for IntCounter + { + type Item = i32; + + fn init() -> i32 { 0 } + + fn next<'c, Value>(f: impl FnOnce(i32) -> Value + 'c) -> WithState<'c, Value, i32> { + WithState::of(move |n| { (f(n), n + 1) }) + } + } + + + pub struct StrCat; + + impl States for StrCat + { + type Item = String; + + fn init() -> String { "a".to_string() } + + fn next<'c, Value>(f: impl FnOnce(Self::Item) -> Value + 'c) -> WithState<'c, Value, Self::Item> { + WithState::of(move |n: String| { let s = n.clone(); (f(n), format!("{}a", s)) }) + } + } +} + +use labelgenerators::*; +use state::WithState; + +// Tree +#[derive(Debug,Clone)] +enum Tree { + Leaf(A), + Node(Box>, Box>) +} + +impl Tree { + fn node(l: Tree, r: Tree) -> Tree { + Tree::Node(Box::new(l), Box::new(r)) + } + + fn label(self) -> Tree + where NodeLabler::Item : Clone { + self.mlabel::().run(NodeLabler::init()).0 + } + + // Monadically label a Tree to Tree + fn mlabel<'c, NodeLabler: States>(self) -> WithState<'c, Tree, NodeLabler::Item> + where NodeLabler::Item : Clone + 'c { + match self { + Tree::Leaf(_) => NodeLabler::next(|n| Tree::Leaf(n)), + Tree::Node(l, r) => { + let (l,r) = (*l, *r); + + l.mlabel::().zip(r.mlabel::()) + .map(|(ll,rr)| Tree::node(ll,rr)) + } + } + } +} + +fn main() { + + let init = Tree::node( + Tree::node( + Tree::Leaf('a'), + Tree::Leaf('b')), + Tree::node( + Tree::node( + Tree::Leaf('c'), + Tree::Leaf('d')), + Tree::Leaf('e')) + ); + + let mapped = init.clone().label::(); + + dbg!(init); + dbg!(mapped); +} +