Skip to content

Instantly share code, notes, and snippets.

@saul
Created March 19, 2022 10:19
Show Gist options
  • Save saul/e72334a7a3d6dc8c9989f978e20693d9 to your computer and use it in GitHub Desktop.
Save saul/e72334a7a3d6dc8c9989f978e20693d9 to your computer and use it in GitHub Desktop.
Rust type equality example
use std::convert::identity;
struct Teq<T, U> {
to: fn(T) -> U,
from: fn(U) -> T,
}
impl<T> Teq<T, T> {
fn refl() -> Teq<T, T> {
Teq {
to: identity,
from: identity,
}
}
}
impl<T, U> Teq<T, U> {
fn cast(self: Self, x: T) -> U {
(self.to)(x)
}
fn cast_from(self: Self, x: U) -> T {
(self.from)(x)
}
}
enum Expr<T> {
Add(Teq<f32, T>, Box<Expr<f32>>, Box<Expr<f32>>),
Subtract(Teq<f32, T>, Box<Expr<f32>>, Box<Expr<f32>>),
Equals(Teq<bool, T>, Box<Expr<f32>>, Box<Expr<f32>>),
If(Box<Expr<bool>>, Box<Expr<T>>, Box<Expr<T>>),
Const(T),
}
impl<T> Expr<T> {
fn eval(self: Self) -> T {
match self {
Expr::Add(teq, l, r) => teq.cast(l.eval() + r.eval()),
Expr::Subtract(teq, l, r) => teq.cast(l.eval() - r.eval()),
Expr::Equals(teq, l, r) => teq.cast(l.eval() == r.eval()),
Expr::If(expr, true_branch, else_branch) => {
if expr.eval() {
true_branch.eval()
} else {
else_branch.eval()
}
}
Expr::Const(value) => value,
}
}
}
fn main() {
let x = Expr::If(
Expr::Equals(
Teq::refl(),
Expr::Const(1.0).into(),
Expr::Const(1.0).into(),
)
.into(),
Expr::Const("they are equal :)").into(),
Expr::Const("they are NOT equal :(").into(),
);
println!("Result: {}", x.eval());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment