| 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 |
} |
|---|