sealed trait ABList[+T] {
def *:[U >: T](x: U): ABList[U] = new *:(x, this)
def map[U](f: T => U): ABList[U]
def foldLeft[Z](z: Z)(f: (Z, T) => Z): Z = z
def foldRight[Z](z: Z)(f: (T, Z) => Z): Z = z
def reduceLeft[Z](f: (Z, T) => Z): Z = sys.error("Nil.reduceLeft")
}
case object ABNil extends ABList[Nothing] {
override def toString: String = "ABList()"
override def map[U](f: _ => U): ABList[U] = this
}
case class *:[+T](x: T, xs: ABList[T]) extends ABList[T] {
private def flip[A, B, C](f: A => B => C)(x: B)(y: A) = f(y)(x)
override def toString = s"ABList(${mkString(", ")})"
override def map[U](f: T => U): ABList[U] = {
foldRight(ABList[U]())((x, acc) => f(x) *: acc)
}
override def foldLeft[Z](z: Z)(f: (Z, T) => Z): Z = {
xs match {
case ABNil => f(z, x)
case _ => xs.foldLeft(f(z, x))(f)
}
}
override def foldRight[Z](z: Z)(f: (T, Z) => Z): Z = {
xs match {
case ABNil => f(x, z)
case _ => f(x, xs.foldRight(z)(f))
}
}
override def reduceLeft[Z](f: (Z, T) => Z): Z = {
(xs foldLeft[Z] x)(f)
}
def mkString(delimiter: String): String = {
reduceLeft[String](_ + delimiter + _)
}
}
object ABList {
def apply[T](as: T*): ABList[T] = if(as.isEmpty) ABNil else *:(as.head, apply(as.tail: _*))
}
object Main extends App {
val list: ABList[Int] = 1 *: 2 *: 3 *: ABNil
println(list.foldLeft(0)(_ + _))
println(list.toString)
}