source: src/metascala/HLists.scala @ 26

Revision 6, 5.7 KB checked in by mayhem, 11 years ago (diff)
Line 
1package metascala
2
3object HLists {
4  import Nats._
5  import Utils._
6
7  sealed trait HList {
8    type Head
9    type Tail <: HList
10    type Append[L <: HList] <: HList
11    type ReverseAppend[L <: HList] <: HList
12    type Length <: Nat
13  }
14
15  final class HNil extends HList {
16    type Head = Nothing
17    type Tail = HNil
18    type Append[L <: HList] = L
19    type ReverseAppend[L <: HList] = L
20    type Length = _0
21
22    def ::[T](v : T) = HCons(v, this)
23    def :::[L <: HList](l : L) = l
24    def reverse = this
25  }
26
27  val HNil = new HNil()
28
29  final case class HCons[H, T <: HList](head : H, tail : T) extends HList {
30    type This = HCons[H, T]
31    type Head = H
32    type Tail = T
33    type Append[L <: HList] = HCons[H, T#Append[L]]
34    type ReverseAppend[L <: HList] = Tail#ReverseAppend[HCons[H, L]]
35    type Length = Succ[T#Length]
36    type GetByType[N <: Nat, E] = GetByTypeFn[This, N, E]
37    type ReplaceByType[N <: Nat, E] = ReplaceByTypeFn[This, N, E]
38
39    def ::[T](v : T) = HCons(v, this)
40    def :::[L <: HList](l : L)(implicit fn : AppendFn[L, This]) = fn(l, this)
41    def nth[N <: Nat](implicit fn : NthFn[This, N]) : NthType[This, N] = fn(this)
42    def reverse(implicit fn : ReverseAppendFn[This, HNil]) = fn(this, HNil)   
43    def remove[N <: Nat](implicit fn : RemoveNthFn[This, N]) = fn(this)
44
45    def insert[N <: Nat, E](n : N, elem : E)(implicit fn : InsertNthFn[This, N, E]) : InsertNthType[This, N, E] = insert[N, E](elem)
46    def insert[N <: Nat, E](elem : E)(implicit fn : InsertNthFn[This, N, E]) : InsertNthType[This, N, E] = fn(this, elem)
47
48    def replaceByType[N <: Nat, E](n : N, elem : E)(implicit fn : ReplaceByType[N, E]) = fn(this, elem)
49    def getByType[N <: Nat, E](implicit fn : GetByType[N, E]) : E = fn(this)
50  }
51 
52  type ::[H, T <: HList] = HCons[H, T]
53
54
55  // Append
56 
57  implicit def hlistNilAppender[L <: HList] = AppendFn[HNil, L]((v : HNil, l : L) => l)
58
59  implicit def hlistConsAppender[H, T <: HList, L2 <: HList, R <: HList]
60    (implicit fn : AppendFn[T, L2]) = AppendFn[HCons[H, T], L2]((l1 : HCons[H, T], l2 : L2) => HCons(l1.head, fn(l1.tail, l2)))
61
62   
63  // Reverse append
64   
65  implicit def hlistNilReverseAppender[L <: HList] = ReverseAppendFn[HNil, L]((v : HNil, l : L) => l)
66
67  implicit def hlistConsReverseAppender[H, T <: HList, L2 <: HList, R <: HList]
68    (implicit fn : ReverseAppendFn[T, HCons[H, L2]]) = ReverseAppendFn[HCons[H, T], L2]((l1 : HCons[H, T], l2 : L2) => fn(l1.tail, HCons(l1.head, l2)))
69
70   
71  // Nth
72   
73  implicit def hlistConsNth0[H, T <: HList] = NthFn[HCons[H, T], _0](l => l.head)
74  implicit def hlistConsNth[H, T <: HList, P <: Nat](implicit fn : NthFn[T, P]) = NthFn[HCons[H, T], Succ[P]](l => fn(l.tail))
75
76 
77  // Remove nth
78
79  implicit def hlistRemoveNth0[H, T <: HList] = RemoveNthFn[HCons[H, T], _0](l => l.tail)
80 
81  implicit def hlistRemoveNth[H, T <: HList, P <: Nat](implicit fn : RemoveNthFn[T, P]) = 
82    RemoveNthFn[HCons[H, T], Succ[P]](l => HCons(l.head, fn(l.tail)))
83
84
85  // Insert nth
86
87  implicit def hlistInsertNth0[L <: HList, E] = InsertNthFn[L, _0, E]((l, elem) => HCons(elem, l))
88 
89  implicit def hlistInsertNth[H, T <: HList, P <: Nat, E](implicit fn : InsertNthFn[T, P, E]) = 
90    InsertNthFn[HCons[H, T], Succ[P], E]((l, elem) => HCons(l.head, fn(l.tail, elem)))
91
92
93  // Replace by type
94
95  implicit def hlistReplaceByType0[T <: HList, E] = ReplaceByTypeFn[HCons[E, T], _0, E]((l, elem) => HCons(elem, l.tail))
96 
97  implicit def hlistReplaceByTypeNthMatch[T <: HList, P <: Nat, E](implicit fn : ReplaceByTypeFn[T, P, E]) = 
98    ReplaceByTypeFn[HCons[E, T], Succ[P], E]((l, elem) => HCons(elem, fn(l.tail, elem)))
99
100  implicit def hlistReplaceByTypeNthNoMatch[H, T <: HList, N <: Nat, E](implicit fn : ReplaceByTypeFn[T, N, E]) = 
101    ReplaceByTypeFn[HCons[H, T], N, E]((l, elem) => HCons(l.head, fn(l.tail, elem)))
102
103
104  // Get by type
105
106  implicit def hlistGetByType0[T <: HList, E] = GetByTypeFn[HCons[E, T], _0, E](l => l.head)
107 
108  implicit def hlistGetByTypeNthMatch[T <: HList, P <: Nat, E](implicit fn : GetByTypeFn[T, P, E]) = 
109    GetByTypeFn[HCons[E, T], Succ[P], E](l => fn(l.tail))
110
111  implicit def hlistGetByTypeNthNoMatch[H, T <: HList, N <: Nat, E](implicit fn : GetByTypeFn[T, N, E]) = 
112    GetByTypeFn[HCons[H, T], N, E](l => fn(l.tail))
113
114
115  case class AppendFn[L1 <: HList, L2 <: HList](fn : (L1, L2) => L1#Append[L2]) extends Fn2Wrapper(fn)
116
117  case class ReverseAppendFn[L1 <: HList, L2 <: HList](fn : (L1, L2) => L1#ReverseAppend[L2]) extends Fn2Wrapper(fn) 
118 
119  case class NthFn[L <: HList, N <: Nat](fn : L => NthType[L, N]) extends Fn1Wrapper(fn)
120
121  final class NthVisitor[L <: HList] extends NatVisitor {
122    type ResultType = Any
123    type Visit0 = L#Head
124    type VisitSucc[Pre <: Nat] = Pre#Accept[NthVisitor[L#Tail]]
125  }
126 
127  type NthType[L <: HList, N <: Nat] = N#Accept[NthVisitor[L]]
128
129  final class RemoveNthVisitor[L <: HList] extends NatVisitor {
130    type ResultType = HList
131    type Visit0 = L#Tail
132    type VisitSucc[Pre <: Nat] = HCons[L#Head, Pre#Accept[RemoveNthVisitor[L#Tail]]]
133  }
134
135  type RemoveNthType[L <: HList, N <: Nat] = N#Accept[RemoveNthVisitor[L]]
136 
137  case class RemoveNthFn[L <: HList, N <: Nat](fn : L => RemoveNthType[L, N]) extends Fn1Wrapper(fn)
138
139  final class InsertNthVisitor[L <: HList, T] extends NatVisitor {
140    type ResultType = HList
141    type Visit0 = HCons[T, L]
142    type VisitSucc[Pre <: Nat] = HCons[L#Head, Pre#Accept[InsertNthVisitor[L#Tail, T]]]
143  }
144
145  type InsertNthType[L <: HList, N <: Nat, E] = N#Accept[InsertNthVisitor[L, E]]
146 
147  case class InsertNthFn[L <: HList, N <: Nat, E](fn : (L, E) => InsertNthType[L, N, E]) extends Fn2Wrapper(fn)
148
149
150  case class ReplaceByTypeFn[L <: HList, N <: Nat, E](fn : (L, E) => L) extends Fn2Wrapper(fn)
151
152  case class GetByTypeFn[L <: HList, N <: Nat, E](fn : L => E) extends Fn1Wrapper(fn)
153
154}
Note: See TracBrowser for help on using the repository browser.