Skip to content

Instantly share code, notes, and snippets.

@Sgeo
Last active February 11, 2016 02:01
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();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment