Last active
November 27, 2024 15:58
-
-
Save Sgeo/ecee21895815fb2066e3 to your computer and use it in GitHub Desktop.
Anonymous sum type prototype
This file contains hidden or 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
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(); | |
} |
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
For example