Created
August 11, 2020 02:36
-
-
Save 9999years/ac0e973c77cb82d98b513e1138105d38 to your computer and use it in GitHub Desktop.
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
//! Kat Spiers has yet again bullied me into writing code. | |
//! Today we worked on type-level arithmetic. | |
use std::ops::{Add, Sub, Mul}; | |
#[derive(Debug, Clone, PartialEq)] | |
enum Kat { | |
Kat(Box<Kat>), | |
Hryn, | |
} | |
impl Kat { | |
fn from_size(size: usize) -> Self { | |
match size { | |
0 => Kat::Hryn, | |
n => Kat::Kat(Kat::from_size(n - 1).into()), | |
} | |
} | |
fn inc(self) -> Self { | |
Kat::Kat(Box::new(self)) | |
} | |
fn dec(self) -> Self { | |
match self { | |
Kat::Kat(kat) => *kat, | |
Kat::Hryn => self, | |
} | |
} | |
fn size(&self) -> usize { | |
match self { | |
Kat::Hryn => 0, | |
Kat::Kat(kat) => 1 + kat.size(), | |
} | |
} | |
} | |
impl From<usize> for Kat { | |
fn from(size: usize) -> Self { | |
Kat::from_size(size) | |
} | |
} | |
impl Add for Kat { | |
type Output = Self; | |
fn add(self, rhs: Self) -> Self { | |
match (self, rhs) { | |
(Kat::Hryn, rhs) => rhs, | |
(lhs, Kat::Hryn) => lhs, | |
(lhs, rhs) => lhs.inc() + rhs.dec(), | |
} | |
} | |
} | |
impl Sub for Kat { | |
type Output = Self; | |
fn sub(self, rhs: Self) -> Self { | |
match (self, rhs) { | |
(Kat::Hryn, _rhs) => Kat::Hryn, | |
(lhs, Kat::Hryn) => lhs, | |
(lhs, rhs) => lhs.inc() - rhs.dec(), | |
} | |
} | |
} | |
impl Mul for Kat { | |
type Output = Self; | |
fn mul(self, rhs: Self) -> Self { | |
match (self, rhs) { | |
(Kat::Hryn, _rhs) => Kat::Hryn, | |
(_lhs, Kat::Hryn) => Kat::Hryn, | |
(Kat::Kat(inner), rhs) if matches!(*inner, Kat::Hryn) => rhs, | |
(lhs, Kat::Kat(inner)) if matches!(*inner, Kat::Hryn) => lhs, | |
(lhs, rhs) => lhs.clone() + lhs * rhs.dec(), | |
} | |
} | |
} | |
fn main() { | |
let eight = Kat::from(5) + Kat::from(3); | |
let also_eight = Kat::from(6) + Kat::from(2); | |
println!("{} = {}", eight.size(), also_eight.size()); | |
println!("8 = 8? {}", eight == also_eight); | |
println!("6 * 2 = {}", (Kat::from(6) * Kat::from(2)).size()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment