Skip to content

Instantly share code, notes, and snippets.

@Sgeo
Last active November 27, 2024 15:58
Show Gist options
  • Save Sgeo/ecee21895815fb2066e3 to your computer and use it in GitHub Desktop.
Save Sgeo/ecee21895815fb2066e3 to your computer and use it in GitHub Desktop.
Anonymous sum type prototype
use std::marker::PhantomData;
pub enum Void {}
impl Void {
fn any(&self) -> ! {
match *self {}
}
}
trait UnwrapVoid<R> {
fn unwrap_void(self) -> R;
}
impl<R> UnwrapVoid<R> for Result<R, Void> {
fn unwrap_void(self) -> R {
match self {
Ok(r) => r,
Err(void) => void.any()
}
}
}
#[allow(dead_code)]
enum Here {}
#[allow(dead_code)]
struct There<T>(PhantomData<T>);
enum Cans<Head, Tail> {
Here(Head),
There(Tail)
}
trait NewCans<Item, Where> {
fn new(item: Item) -> Self;
}
impl<Item, Tail> NewCans<Item, Here> for Cans<Item, Tail> {
fn new(item: Item) -> Self {
Cans::Here(item)
}
}
impl<Item, Head, Tail, TailIndex> NewCans<Item, There<TailIndex>> for Cans<Head, Tail>
where Tail: NewCans<Item, TailIndex> {
fn new(item: Item) -> Self {
Cans::There(NewCans::new(item))
}
}
impl<Head, Tail> Cans<Head, Tail> {
pub fn new<Item, Where>(item: Item) -> Self
where Self: NewCans<Item, Where> {
NewCans::new(item)
}
}
trait Find<T, Where> {
fn find(&self) -> Option<&T>;
fn find_mut(&mut self) -> Option<&mut T>;
}
impl<T, Tail> Find<T, Here> for Cans<T, Tail> {
fn find(&self) -> Option<&T> {
match *self {
Cans::Here(ref t) => Some(t),
Cans::There(_) => None,
}
}
fn find_mut(&mut self) -> Option<&mut T> {
match *self {
Cans::Here(ref mut t) => Some(t),
Cans::There(_) => None
}
}
}
impl<Head, T, Tail, TailIndex> Find<T, There<TailIndex>> for Cans<Head, Tail>
where Tail: Find<T, TailIndex> {
fn find(&self) -> Option<&T> {
match *self {
Cans::Here(_) => None,
Cans::There(ref there) => there.find()
}
}
fn find_mut(&mut self) -> Option<&mut T> {
match *self {
Cans::Here(_) => None,
Cans::There(ref mut there) => there.find_mut()
}
}
}
trait Select<T, R, Where> {
type Remainder;
fn select<F>(self, F) -> Result<R, Self::Remainder>
where F: FnOnce(T) -> R;
}
impl<T, R, Tail> Select<T, R, Here> for Cans<T, Tail> {
type Remainder = Tail;
fn select<F>(self, f: F) -> Result<R, Self::Remainder>
where F: FnOnce(T) -> R {
match self {
Cans::Here(t) => Ok(f(t)),
Cans::There(there) => Err(there)
}
}
}
impl<T, R, Head, Tail, TailIndex> Select<T, R, There<TailIndex>> for Cans<Head, Tail>
where Tail: Select<T, R, TailIndex> {
type Remainder = Cans<Head, Tail::Remainder>;
fn select<F>(self, f: F) -> Result<R, Self::Remainder>
where F: FnOnce(T) -> R {
match self {
Cans::Here(t) => Err(Cans::Here(t)),
Cans::There(there) => there.select(f).map_err(|tail| Cans::There(tail))
}
}
}
impl<T, R, Selectable, Index> Select<T, R, Index> for Result<R, Selectable>
where Selectable: Select<T, R, Index> {
type Remainder = Selectable::Remainder;
fn select<F>(self, f: F) -> Result<R, Self::Remainder>
where F: FnOnce(T) -> R{
self.or_else(|sel| sel.select(f))
}
}
trait Reshape<Dest, Indices> {
fn reshape(self) -> Dest;
}
impl<Dest> Reshape<Dest, ()> for Void {
fn reshape(self) -> Dest {
self.any()
}
}
impl<Dest, SHead, STail, HIndex, TIndices> Reshape<Dest, (HIndex, TIndices)> for Cans<SHead, STail>
where STail: Reshape<Dest, TIndices>,
Dest: NewCans<SHead, HIndex> {
fn reshape(self) -> Dest {
match self {
Cans::Here(shead) => NewCans::new(shead),
Cans::There(stail) => stail.reshape()
}
}
}
fn main() {
let cans: Cans<i32, Cans<String, Void>> = Cans::new("Hello".to_string());
{
let s: Option<&String> = cans.find();
let t: Option<&i32> = cans.find();
println!("{:?}", s);
println!("{:?}", t);
}
let foo = cans.select(|s: String| "It's a string!").select(|i: i32| "It's an i32!").unwrap_void();
println!("{:?}", foo);
let cans2: Cans<i32, Cans<String, Void>> = Cans::new("Hello".to_string());
let cans3: Cans<String, Cans<i32, Cans<i64, Void>>> = cans2.reshape();
}
@ay0ks
Copy link

ay0ks commented Nov 15, 2024

Reshape could be left as is instead of Mash

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment