|
13 | 13 | use std::ops::*;
|
14 | 14 |
|
15 | 15 | #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
16 |
| -struct Nil; // empty HList |
| 16 | +struct Nil; |
| 17 | + // empty HList |
17 | 18 | #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
18 |
| -struct Cons<H, T: HList>(H, T); // cons cell of HList |
| 19 | +struct Cons<H, T: HList>(H, T); |
| 20 | + // cons cell of HList |
19 | 21 |
|
20 |
| -// trait to classify valid HLists |
21 |
| -trait HList {} |
22 |
| -impl HList for Nil {} |
23 |
| -impl<H, T: HList> HList for Cons<H, T> {} |
| 22 | + // trait to classify valid HLists |
| 23 | +trait HList { } |
| 24 | +impl HList for Nil { } |
| 25 | +impl <H, T: HList> HList for Cons<H, T> { } |
24 | 26 |
|
25 | 27 | // term-level macro for HLists
|
26 |
| -macro_rules! hlist { |
27 |
| - {} => { Nil }; |
28 |
| - { $head:expr } => { Cons($head, Nil) }; |
29 |
| - { $head:expr, $($tail:expr),* } => { Cons($head, hlist!($($tail),*)) }; |
30 |
| -} |
| 28 | +macro_rules! hlist({ } => { Nil } ; { $ head : expr } => { |
| 29 | + Cons ( $ head , Nil ) } ; { |
| 30 | + $ head : expr , $ ( $ tail : expr ) , * } => { |
| 31 | + Cons ( $ head , hlist ! ( $ ( $ tail ) , * ) ) } ;); |
31 | 32 |
|
32 | 33 | // type-level macro for HLists
|
33 |
| -macro_rules! HList { |
34 |
| - {} => { Nil }; |
35 |
| - { $head:ty } => { Cons<$head, Nil> }; |
36 |
| - { $head:ty, $($tail:ty),* } => { Cons<$head, HList!($($tail),*)> }; |
37 |
| -} |
| 34 | +macro_rules! HList({ } => { Nil } ; { $ head : ty } => { |
| 35 | + Cons < $ head , Nil > } ; { |
| 36 | + $ head : ty , $ ( $ tail : ty ) , * } => { |
| 37 | + Cons < $ head , HList ! ( $ ( $ tail ) , * ) > } ;); |
38 | 38 |
|
39 | 39 | // nil case for HList append
|
40 |
| -impl<Ys: HList> Add<Ys> for Nil { |
41 |
| - type Output = Ys; |
| 40 | +impl <Ys: HList> Add<Ys> for Nil { |
| 41 | + type |
| 42 | + Output |
| 43 | + = |
| 44 | + Ys; |
42 | 45 |
|
43 |
| - fn add(self, rhs: Ys) -> Ys { |
44 |
| - rhs |
45 |
| - } |
| 46 | + fn add(self, rhs: Ys) -> Ys { rhs } |
46 | 47 | }
|
47 | 48 |
|
48 | 49 | // cons case for HList append
|
49 |
| -impl<Rec: HList + Sized, X, Xs: HList, Ys: HList> Add<Ys> for Cons<X, Xs> where |
50 |
| - Xs: Add<Ys, Output = Rec>, |
51 |
| -{ |
52 |
| - type Output = Cons<X, Rec>; |
| 50 | +impl <Rec: HList + Sized, X, Xs: HList, Ys: HList> Add<Ys> for Cons<X, Xs> |
| 51 | + where Xs: Add<Ys, Output = Rec> { |
| 52 | + type |
| 53 | + Output |
| 54 | + = |
| 55 | + Cons<X, Rec>; |
53 | 56 |
|
54 |
| - fn add(self, rhs: Ys) -> Cons<X, Rec> { |
55 |
| - Cons(self.0, self.1 + rhs) |
56 |
| - } |
| 57 | + fn add(self, rhs: Ys) -> Cons<X, Rec> { Cons(self.0, self.1 + rhs) } |
57 | 58 | }
|
58 | 59 |
|
59 | 60 | // type macro Expr allows us to expand the + operator appropriately
|
60 |
| -macro_rules! Expr { |
61 |
| - { ( $($LHS:tt)+ ) } => { Expr!($($LHS)+) }; |
62 |
| - { HList ! [ $($LHS:tt)* ] + $($RHS:tt)+ } => { |
63 |
| - <Expr!(HList![$($LHS)*]) as Add<Expr!($($RHS)+)>>::Output |
64 |
| - }; |
65 |
| - { $LHS:tt + $($RHS:tt)+ } => { <Expr!($LHS) as Add<Expr!($($RHS)+)>>::Output }; |
66 |
| - { $LHS:ty } => { $LHS }; |
67 |
| -} |
| 61 | +macro_rules! Expr({ ( $ ( $ LHS : tt ) + ) } => { Expr ! ( $ ( $ LHS ) + ) } ; |
| 62 | + { HList ! [ $ ( $ LHS : tt ) * ] + $ ( $ RHS : tt ) + } => { |
| 63 | + < Expr ! ( HList ! [ $ ( $ LHS ) * ] ) as Add < Expr ! ( |
| 64 | + $ ( $ RHS ) + ) >> :: Output } ; { |
| 65 | + $ LHS : tt + $ ( $ RHS : tt ) + } => { |
| 66 | + < Expr ! ( $ LHS ) as Add < Expr ! ( $ ( $ RHS ) + ) >> :: |
| 67 | + Output } ; { $ LHS : ty } => { $ LHS } ;); |
68 | 68 |
|
69 | 69 | // test demonstrating term level `xs + ys` and type level `Expr!(Xs + Ys)`
|
70 | 70 | fn main() {
|
71 |
| - fn aux<Xs: HList, Ys: HList>(xs: Xs, ys: Ys) -> Expr!(Xs + Ys) |
72 |
| - where Xs: Add<Ys> { |
73 |
| - xs + ys |
74 |
| - } |
| 71 | + fn aux<Xs: HList, Ys: HList>(xs: Xs, ys: Ys) -> Expr!(Xs + Ys) where |
| 72 | + Xs: Add<Ys> { |
| 73 | + xs + ys |
| 74 | + } |
75 | 75 |
|
76 |
| - let xs: HList![&str, bool, Vec<u64>] = hlist!["foo", false, vec![]]; |
77 |
| - let ys: HList![u64, [u8; 3], ()] = hlist![0, [0, 1, 2], ()]; |
| 76 | + let xs: HList!(& str , bool , Vec < u64 >) = |
| 77 | + hlist!("foo" , false , vec ! [ ]); |
| 78 | + let ys: HList!(u64 , [ u8 ; 3 ] , ( )) = |
| 79 | + hlist!(0 , [ 0 , 1 , 2 ] , ( )); |
78 | 80 |
|
79 | 81 | // demonstrate recursive expansion of Expr!
|
80 |
| - let zs: Expr!((HList![&str] + HList![bool] + HList![Vec<u64>]) + |
81 |
| - (HList![u64] + HList![[u8; 3], ()]) + |
82 |
| - HList![]) |
83 |
| - = aux(xs, ys); |
84 |
| - assert_eq!(zs, hlist!["foo", false, vec![], 0, [0, 1, 2], ()]) |
| 82 | + let zs: |
| 83 | + Expr!(( |
| 84 | + HList ! [ & str ] + HList ! [ bool ] + HList ! [ Vec < u64 > |
| 85 | + ] ) + ( HList ! [ u64 ] + HList ! [ [ u8 ; 3 ] , ( ) ] ) + |
| 86 | + HList ! [ ]) = aux(xs, ys); |
| 87 | + assert_eq!(zs , hlist ! [ |
| 88 | + "foo" , false , vec ! [ ] , 0 , [ 0 , 1 , 2 ] , ( ) ]) |
85 | 89 | }
|
86 |
| - |
|
0 commit comments