
List(1, 2, 7, 9) is a Vector[Int]abstract class GList[+E] {
def head: E
def tail: GList[E]
def isEmpty: Boolean
...
}+E means that type parameter is covariant:
GList[String] to a GList[Any]def ::[H >: E](h: H): GList[H] = new GNonEmpty(h, this)
42 :: "Fred" :: GEmpty is a List[Any]GEmpty doesn't have a type parameter:
case object GEmpty extends GList[Nothing] { ... }
List[Any] isn't so great:
val lst = 1 :: "Fred" :: Nil val str = lst.tail.head.toUpperCase // Won't compile
abstract class HList[H, T <: HList[_, _]] {
def head: H
def tail: T
}
case object HEmpty extends HList[Nothing, Nothing] {
def head = ???
def tail = ???
def ::[A](a: A) = HNonEmpty(a, this)
}
case class HNonEmpty[H, T <: HList[_, _]](head: H, tail: T) extends HList[H, T] {
def ::[A](a: A) = HNonEmpty(a, this)
}
HList has a type that matches the element types:
val lst = 42 :: "Fred" :: HEmpty // has type HNonEmpty[Int, HNonEmpty[String, HEmpty.type]]
type ::[H, T <: HList[_, _]] = HNonEmpty[H, T] type HNil = HEmpty.type val result: Int :: String :: HNil = lst
abstract class HList[H, T <: HList[_, _]] {
def append[L <: HList[_, _]](lst: L): __________
}abstract class HList[H, T <: HList[_, _]] {
...
type Append[L <: HList[_, _]] <: HList[_, _]
def append[L <: HList[_, _]](lst: L): Append[L]
}
case object HEmpty extends HList[Nothing, Nothing] {
...
type Append[L <: HList[_, _]] = L
def append[L <: HList[_, _]](lst: L) = lst
}
case class HNonEmpty[H, T <: HList[_, _]](head: H, tail: T) extends HList[H, T] {
...
type Append[L <: HList[_, _]] = HNonEmpty[H, T#Append[L]]
def append[L <: HList[_, _]](lst: L) = HNonEmpty(head, tail.append(lst))
}val lst = 42 :: "Fred" :: HEmpty // Type Int :: String :: HNil val lst2 = lst.append(lst) // Type Int :: String :: Int :: String :: HNil
abstract class JsonConverter[T] { // like Java interface
def convert(t: T): String
}def toJson[T](t: T, converter: JsonConverter[T]) = converter.convert(t)
implicit object stringJsonConverter extends JsonConverter[String] {
def convert(t: String) = "\"" + t.replace("\\", "\\\\").replace("\"", "\\\"") + "\""
}
def toJson[T](t: T)(implicit converter: JsonConverter[T]) = converter.convert(t)
toJson("Fred") compiles, but json(new File("Fred")) doesn't.toJson function:
def toJson[T : JsonConverter](t: T) = implicitly[JsonConverter[T]].convert(t)
implicit object listJsonConverter[E]. Workaround:
implicit def listJsonConverter[E : JsonConverter]:
JsonConverter[List[E]] = new JsonConverter[List[E]] {
def convert(ts: List[E]) = ts.map(toJson(_)).mkString("[", ",", "]")
}toJson(List("Fred", "Wilma"))
toJson(List(List(1, 7), List(2, 9)))
but not
toJson(List(new File("Fred"), new File("Wilma")))
