// run-pass #![allow(unused_macro_rules)] use std::ops::*; #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] struct Nil; // empty HList #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] struct Cons(H, T); // cons cell of HList // trait to classify valid HLists trait HList { } impl HList for Nil { } impl HList for Cons { } // term-level macro for HLists macro_rules! hlist({ } => { Nil } ; { $ head : expr } => { Cons ( $ head , Nil ) } ; { $ head : expr , $ ( $ tail : expr ) , * } => { Cons ( $ head , hlist ! ( $ ( $ tail ) , * ) ) } ;); // type-level macro for HLists macro_rules! HList({ } => { Nil } ; { $ head : ty } => { Cons < $ head , Nil > } ; { $ head : ty , $ ( $ tail : ty ) , * } => { Cons < $ head , HList ! ( $ ( $ tail ) , * ) > } ;); // nil case for HList append impl Add for Nil { type Output = Ys; fn add(self, rhs: Ys) -> Ys { rhs } } // cons case for HList append impl Add for Cons where Xs: Add { type Output = Cons; fn add(self, rhs: Ys) -> Cons { Cons(self.0, self.1 + rhs) } } // type macro Expr allows us to expand the + operator appropriately macro_rules! Expr({ ( $ ( $ LHS : tt ) + ) } => { Expr ! ( $ ( $ LHS ) + ) } ; { HList ! [ $ ( $ LHS : tt ) * ] + $ ( $ RHS : tt ) + } => { < Expr ! ( HList ! [ $ ( $ LHS ) * ] ) as Add < Expr ! ( $ ( $ RHS ) + ) >> :: Output } ; { $ LHS : tt + $ ( $ RHS : tt ) + } => { < Expr ! ( $ LHS ) as Add < Expr ! ( $ ( $ RHS ) + ) >> :: Output } ; { $ LHS : ty } => { $ LHS } ;); // test demonstrating term level `xs + ys` and type level `Expr!(Xs + Ys)` fn main() { fn aux(xs: Xs, ys: Ys) -> Expr!(Xs + Ys) where Xs: Add { xs + ys } let xs: HList!(& str , bool , Vec < u64 >) = hlist!("foo" , false , vec ! [ ]); let ys: HList!(u64 , [ u8 ; 3 ] , ( )) = hlist!(0 , [ 0 , 1 , 2 ] , ( )); // demonstrate recursive expansion of Expr! let zs: Expr!(( HList ! [ & str ] + HList ! [ bool ] + HList ! [ Vec < u64 > ] ) + ( HList ! [ u64 ] + HList ! [ [ u8 ; 3 ] , ( ) ] ) + HList ! [ ]) = aux(xs, ys); assert_eq!(zs , hlist ! [ "foo" , false , vec ! [ ] , 0 , [ 0 , 1 , 2 ] , ( ) ]) }