summaryrefslogtreecommitdiff
path: root/reversible.rs
diff options
context:
space:
mode:
Diffstat (limited to 'reversible.rs')
-rw-r--r--reversible.rs158
1 files changed, 158 insertions, 0 deletions
diff --git a/reversible.rs b/reversible.rs
new file mode 100644
index 0000000..19e6f98
--- /dev/null
+++ b/reversible.rs
@@ -0,0 +1,158 @@
+use std::marker::PhantomData;
+
+pub trait Rev {
+ type Input;
+ type Output;
+
+ fn forward(&self, i: Self::Input) -> Self::Output;
+ fn reverse(&self, o: Self::Output) -> Self::Input;
+}
+
+#[derive(Clone)]
+pub struct Addition<A> {
+ amount: A
+}
+impl<A> Rev for Addition<A>
+where
+ A: std::ops::Add<Output = A> + std::ops::Sub<Output = A> + Copy
+{
+ type Input = A;
+ type Output = A;
+
+ fn forward(&self, a: A) -> A {
+ a + self.amount
+ }
+
+ fn reverse(&self, b: A) -> A {
+ b - self.amount
+ }
+}
+pub fn plus<A>(amount: A) -> Addition<A> {
+ Addition { amount }
+}
+
+// more blocks
+
+#[derive(Clone)]
+pub struct Negate<A>(PhantomData<A>);
+impl<A: std::ops::Neg<Output = A>> Rev for Negate<A> {
+ type Input = A;
+ type Output = A;
+
+ fn forward(&self, a: Self::Input) -> Self::Output {
+ -a
+ }
+
+ fn reverse(&self, b: Self::Output) -> Self::Input {
+ -b
+ }
+}
+pub fn neg<A>() -> Negate<A> {
+ Negate(PhantomData)
+}
+
+#[derive(Clone)]
+pub struct Multiplication<A> {
+ amount: A
+}
+impl<A> Rev for Multiplication<A>
+where
+ A: std::ops::Mul<Output = A> + std::ops::Div<Output = A> + Copy,
+{
+ type Input = A;
+ type Output = A;
+
+ fn forward(&self, a: A) -> A {
+ a * self.amount
+ }
+
+ fn reverse(&self, b: A) -> A {
+ b / self.amount
+ }
+}
+pub fn times<A>(amount: A) -> Multiplication<A> {
+ Multiplication { amount }
+}
+
+#[derive(Clone)]
+pub struct DiscreteMap<A, B>(Vec<(A, B)>);
+impl<A: PartialEq + Clone, B: PartialEq + Clone> Rev for DiscreteMap<A, B> {
+ type Input = A;
+ type Output = B;
+
+ fn forward(&self, a: A) -> B {
+ for i in self.0.iter() {
+ if i.0 == a {
+ return i.1.clone()
+ }
+ }
+ panic!()
+ }
+
+ fn reverse(&self, b: B) -> A {
+ for i in self.0.iter() {
+ if i.1 == b {
+ return i.0.clone()
+ }
+ }
+ panic!()
+ }
+}
+pub fn discrete<A, B>(vec: Vec<(A, B)>) -> DiscreteMap<A, B> {
+ DiscreteMap(vec)
+}
+
+// combinators
+
+#[derive(Clone)]
+pub struct Pipe<X, Y>(X, Y);
+impl<X, Y> Rev for Pipe<X, Y>
+where
+ X: Rev,
+ Y: Rev<Input = X::Output>
+{
+ type Input = X::Input;
+ type Output = Y::Output;
+
+ fn forward(&self, a: Self::Input) -> Self::Output {
+ self.1.forward(self.0.forward(a))
+ }
+
+ fn reverse(&self, c: Self::Output) -> Self::Input {
+ self.0.reverse(self.1.reverse(c))
+ }
+}
+
+#[derive(Clone)]
+pub struct Inverse<X>(X);
+impl<X: Rev> Rev for Inverse<X> {
+ type Input = X::Output;
+ type Output = X::Input;
+
+ fn forward(&self, a: Self::Input) -> Self::Output {
+ self.0.reverse(a)
+ }
+
+ fn reverse(&self, b: Self::Output) -> Self::Input {
+ self.0.forward(b)
+ }
+}
+
+pub trait RevExt: Rev + Sized {
+ fn then<N: Rev<Input = Self::Output>>(self, other: N) -> Pipe<Self, N> {
+ Pipe(self, other)
+ }
+
+ fn inverse(self) -> Inverse<Self> {
+ Inverse(self)
+ }
+}
+impl<T: Rev> RevExt for T {}
+
+pub fn under<Op, Val>(op: Op, val: Val) -> impl Rev<Input = Op::Input, Output = Op::Input>
+where
+ Op: Rev + Clone,
+ Val: Rev<Input = Op::Output, Output = Op::Output>
+{
+ op.clone().then(val).then(op.inverse())
+} \ No newline at end of file