Created
October 4, 2020 15:35
-
-
Save derrickturk/0d748400e48c361106ef7d48c60a4d99 to your computer and use it in GitHub Desktop.
Well-typed (ish) HLists and named tuples in Rust, with const generics
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
use std::marker::PhantomData; | |
pub trait Ix { } | |
pub trait HList { } | |
pub trait Ixed<T, N> { | |
fn get(&self) -> &T; | |
fn get_mut(&mut self) -> &mut T; | |
} | |
pub struct Z; | |
impl Ix for Z { } | |
pub struct S<N> { | |
_marker: PhantomData<N>, | |
} | |
impl<N: Ix> Ix for S<N> { } | |
#[derive(Debug, Copy, Clone)] | |
pub struct HNil; | |
impl HList for HNil { } | |
#[derive(Debug, Copy, Clone)] | |
pub struct HCons<T, Tail> { | |
pub head: T, | |
pub tail: Tail, | |
} | |
impl<T, Tail: HList> HList for HCons<T, Tail> { } | |
impl<T, Tail> Ixed<T, Z> for HCons<T, Tail> { | |
fn get(&self) -> &T { | |
&self.head | |
} | |
fn get_mut(&mut self) -> &mut T { | |
&mut self.head | |
} | |
} | |
impl<T, U, N, Tail: Ixed<U, N>> Ixed<U, S<N>> for HCons<T, Tail> { | |
fn get(&self) -> &U { | |
self.tail.get() | |
} | |
fn get_mut(&mut self) -> &mut U { | |
self.tail.get_mut() | |
} | |
} | |
#[inline] | |
pub fn get<N, T, H: Ixed<T, N>>(hlist: &H) -> &T { | |
hlist.get() | |
} | |
#[inline] | |
pub fn get_mut<N, T, H: Ixed<T, N>>(hlist: &mut H) -> &mut T { | |
hlist.get_mut() | |
} |
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
use crate::hlist::*; | |
#[derive(Debug, Copy, Clone)] | |
pub struct Named<T, const NAME: &'static str>(T); | |
#[derive(Debug, Copy, Clone)] | |
pub struct NamedTuple<H>(H); | |
impl NamedTuple<HNil> { | |
pub fn new() -> Self { | |
NamedTuple(HNil) | |
} | |
} | |
impl<H: HList> NamedTuple<H> { | |
pub fn add<const NAME: &'static str, T>(self, val: T) -> NamedTuple<HCons<Named<T, NAME>, H>> { | |
NamedTuple(HCons { | |
head: Named(val), | |
tail: self.0, | |
}) | |
} | |
} | |
#[inline] | |
pub fn nt_get<T, H, N, const NAME: &'static str>(nt: &NamedTuple<H>) -> &T | |
where H: Ixed<Named<T, NAME>, N> { | |
&nt.0.get().0 | |
} | |
#[inline] | |
pub fn nt_get_mut<T, H, N, const NAME: &'static str>(nt: &mut NamedTuple<H>) -> &mut T | |
where H: Ixed<Named<T, NAME>, N> { | |
&mut nt.0.get_mut().0 | |
} |
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
#![feature(const_generics)] | |
mod hlist; | |
use hlist::*; | |
mod namedtuple; | |
use namedtuple::*; | |
fn main() { | |
let mut xs = HCons { | |
head: 3, | |
tail: HCons { | |
head: "yo", | |
tail: HNil, | |
} | |
}; | |
dbg!(get::<Z, _, _>(&xs)); | |
dbg!(get::<S<Z>, _, _>(&xs)); | |
*get_mut::<_, &str, _>(&mut xs) = "joe"; | |
dbg!(get::<S<Z>, _, _>(&xs)); | |
let nt = NamedTuple::new(); | |
let nt = nt.add::<"first_name", _>("joe"); | |
let nt = nt.add::<"last_name", _>("smith"); | |
let mut nt = nt.add::<"age", _>(32); | |
dbg!(nt_get::<_, _, _, "first_name">(&nt)); | |
*nt_get_mut::<_, _, _, "first_name">(&mut nt) = "bob"; | |
dbg!(nt_get::<_, _, _, "first_name">(&nt)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment