Assembla home | Assembla project page
 

root/src/metascala/HLists.scala

Revision 6, 5.7 kB (checked in by mayhem, 1 year ago)

--

Line 
1 package metascala
2
3 object 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 browser.