这个例子来源于scala圣经级教程《Functional Programming in Scala》,由于本人跟着书中的代码敲了一遍,然后写了点测试代码验证了一下正确性,所以就放在这做个备忘吧。贴出来只是为了方便自己,如果看不懂,但是又感兴趣的就去看原书吧。
package fpinscala.datastructures
sealed trait List[+A]
case object Nil extends List[Nothing]
case class Cons[+A](head: A, tail: List[A]) extends List[A]
object List {
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(x, xs) => x + sum(xs)
}
def product(ds: List[Double]): Double = ds match {
case Nil => 1.0
case Cons(0.0, _) => 0.0
case Cons(x, xs) => x * product(xs)
}
def apply[A](as: A*): List[A] = if (as.isEmpty) Nil else Cons(as.head, apply(as.tail: _*))
def append[A](a1: List[A], a2: List[A]): List[A] =
a1 match {
case Nil => a2
case Cons(h, t) => Cons(h, append(t, a2))
}
def sum2(ns: List[Int]) = foldRight(ns, 0)(_ + _)
def product2(ns: List[Double]) = foldRight(ns, 1.0)(_ * _)
def tail[A](l: List[A]): List[A] = l match {
case Nil => sys.error("tail of empty list")
case Cons(_, t) => t
}
def setHead[A](l: List[A], h: A): List[A] = l match {
case Nil => sys.error("tail of empty list")
case Cons(_, t) => Cons(h, t)
}
def drop[A](l: List[A], n: Int): List[A] =
if (n <= 0) l else l match {
case Nil => Nil
case Cons(_, t) => drop(t, n - 1)
}
def dropWhile[A](l: List[A], f: A => Boolean): List[A] =
l match {
case Cons(h, t) if f(h) => dropWhile(t, f)
case _ => l
}
def init[A](l: List[A]): List[A] = l match {
case Nil => sys.error("init of empty list")
case Cons(_, Nil) => Nil
case Cons(h, t) => Cons(h, init(t))
}
def init2[A](l: List[A]): List[A] = {
import scala.collection.mutable.ListBuffer;
val buf = new ListBuffer[A];
@annotation.tailrec
def go(cur: List[A]): List[A] = cur match {
case Nil => sys.error("init of empty list")
case Cons(_, Nil) => List(buf.toList: _*)
case Cons(h, t) => buf += h; go(t)
}
go(l)
}
def lenght[A](l: List[A]): Int = foldRight(l, 0)((_, acc) => acc + 1)
def sum3(l: List[Int]): Int = foldLeft(l, 0)(_ + _)
def product3(l: List[Double]) = foldLeft(l, 1.0)(_ * _)
def length2[A](l: List[A]): Int = foldLeft(l, 0)((acc, _) => acc + 1)
def reverse[A](l: List[A]): List[A] = foldLeft(l, List[A]())((acc, h) => Cons(h, acc))
def foldRightViaFoldLeft[A, B](l: List[A], z: B)(f: (A, B) => B): B = foldLeft(reverse(l), z)((b, a) => f(a, b))
def foldRight[A, B](as: List[A], z: B)(f: (A, B) => B): B =
as match {
case Nil => z
case Cons(x, xs) => f(x, foldRight(xs, z)(f))
}
@annotation.tailrec
def foldLeft[A, B](l: List[A], z: B)(f: (B, A) => B): B = l match {
case Nil => z
case Cons(h, t) => foldLeft(t, f(z, h))(f)
}
def foldRightViaFoldLeft_1[A, B](l: List[A], z: B)(f: (A, B) => B) =
foldLeft(l, (b: B) => b)((g, a) => b => g(f(a, b)))(z)
def foldLeftViaFoldRight[A, B](l: List[A], z: B)(f: (B, A) => B): B =
foldRight(l, (b: B) => b)((a, g) => b => g(f(b, a)))(z)
def appendViaFoldRight[A](l: List[A], r: List[A]): List[A] =
foldRight(l, r)(Cons(_, _))
def concat[A](l: List[List[A]]): List[A] = foldRight(l, Nil: List[A])(append)
def add1(l: List[Int]): List[Int] = foldRight(l, Nil: List[Int])((h, t) => Cons(h + 1, t))
def doubleToString(l: List[Double]): List[String] =
foldRight(l, Nil: List[String])((h, t) => Cons(h.toString, t))
def map[A, B](l: List[A])(f: A => B): List[B] =
foldRight(l, Nil: List[B])((h, t) => Cons(f(h), t))
def map_1[A, B](l: List[A])(f: A => B): List[B] =
foldRightViaFoldLeft(l, Nil: List[B])((h, t) => Cons(f(h), t))
def map_2[A, B](l: List[A])(f: A => B): List[B] = {
val buf = new scala.collection.mutable.ListBuffer[B]
def go(l: List[A]): Unit = l match {
case Nil => ()
case Cons(h, t) => buf += f(h); go(t)
}
go(l)
List(buf.toList: _*)
}
def filter[A](l: List[A])(f: A => Boolean): List[A] =
foldRight(l, Nil: List[A])((h, t) => if(f(h)) Cons(h, t) else t)
def filter_1[A](l: List[A])(f: A => Boolean): List[A] =
foldRightViaFoldLeft(l, Nil: List[A])((h, t) => if(f(h)) Cons(h, t) else t)
def filter_2[A](l: List[A])(f: A => Boolean): List[A] = {
val buf = new scala.collection.mutable.ListBuffer[A]
def go(l: List[A]): Unit = l match {
case Nil => ()
case Cons(h, t) => if(f(h)) buf += h; go(t)
}
go(l)
List(buf.toList: _*)
}
def flatMap[A, B](l: List[A])(f: A => List[B]): List[B] =
concat(map(l)(f))
def filterViaFlatMap[A](l: List[A])(f: A => Boolean): List[A] =
flatMap(l)(a => if(f(a)) List(a) else Nil)
def addPairWise(a: List[Int], b: List[Int]): List[Int] = (a, b) match {
case (Nil, _) => Nil
case (_, Nil) => Nil
case (Cons(h1, t1), Cons(h2, t2)) => Cons(h1 + h2, addPairWise(t1, t2))
}
def zipWith[A, B, C](a: List[A], b: List[B])(f: (A, B) => C): List[C] = (a, b) match {
case (Nil, _) => Nil
case (_, Nil) => Nil
case (Cons(h1, t1), Cons(h2, t2)) => Cons(f(h1, h2), zipWith(t1, t2)(f))
}
@annotation.tailrec
def startWith[A](l: List[A], prefix: List[A]): Boolean = (l, prefix) match {
case (_, Nil) => true
case (Cons(h, t), Cons(h2, t2)) if h == h2 => startWith(t, t2)
case _ => false
}
@annotation.tailrec
def hasSubsequence[A](sup: List[A], sub: List[A]): Boolean = sup match {
case Nil => sub == Nil
case _ if startWith(sup, sub) => true
case Cons(h, t) => hasSubsequence(t, sub)
}
/**
* 测试
* @author lihong10 2018/7/3 10:07:00
* @param args
* return void
*/
def main(args: Array[String]): Unit = {
val liStr: List[String] = List("wo", "shi", "zhong", "guo", "ren", "ni", "shi", "sha", "bi")
val liStrSub = List("ni", "shi", "sha", "bi")
println(liStr)
val hasSubSeq = List.hasSubsequence(liStr, liStrSub)
println(hasSubSeq)
val doubleELe = List.map(liStr)((a: String) => a * 2)
println(doubleELe)
val lenGt3 = List.filter(liStr)((a: String) => a.length > 3)
println(lenGt3)
println(List.lenght(liStr))
val liInt = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
val add1 = List.add1(liInt)
println(add1)
println("sum:" + List.sum(liInt))
println("foldLeft with 1000: " + List.foldLeft(liInt, 1000)(_ + _))
println(List.reverse(liInt))
val init = List.init(liInt)
println("init: " + init)
val tail = List.tail(liInt)
println("tail: " + tail)
val dropLe5 = List.dropWhile(liInt, (a: Int) => a <= 5)
println(dropLe5)
val lili = List(List(1, 3, 5, 7), List(2, 4, 6, 8))
val concated = List.concat(lili)
println(concated)
val zipList = List.zipWith(List(1, 3, 5, 7), List(2, 4, 6, 8))((_, _))
println(zipList)
val addPair = List.addPairWise(List(1, 2, 3, 4), List(4, 3, 2, 1))
println(addPair)
val join = List.foldRightViaFoldLeft(List(1, 3, 5, 7, 9, 11, 13, 15, 17, 19), "")((a: Int, b: String) => b + a.toString)
println(join)
}
}
上述代码的运行结果是:
Cons(wo,Cons(shi,Cons(zhong,Cons(guo,Cons(ren,Cons(ni,Cons(shi,Cons(sha,Cons(bi,Nil)))))))))
true
Cons(wowo,Cons(shishi,Cons(zhongzhong,Cons(guoguo,Cons(renren,Cons(nini,Cons(shishi,Cons(shasha,Cons(bibi,Nil)))))))))
Cons(zhong,Nil)
9
Cons(2,Cons(3,Cons(4,Cons(5,Cons(6,Cons(7,Cons(8,Cons(9,Cons(10,Nil)))))))))
sum:45
foldLeft with 1000: 1045
Cons(9,Cons(8,Cons(7,Cons(6,Cons(5,Cons(4,Cons(3,Cons(2,Cons(1,Nil)))))))))
init: Cons(1,Cons(2,Cons(3,Cons(4,Cons(5,Cons(6,Cons(7,Cons(8,Nil))))))))
tail: Cons(2,Cons(3,Cons(4,Cons(5,Cons(6,Cons(7,Cons(8,Cons(9,Nil))))))))
Cons(6,Cons(7,Cons(8,Cons(9,Nil))))
Cons(1,Cons(3,Cons(5,Cons(7,Cons(2,Cons(4,Cons(6,Cons(8,Nil))))))))
Cons((1,2),Cons((3,4),Cons((5,6),Cons((7,8),Nil))))
Cons(5,Cons(5,Cons(5,Cons(5,Nil))))
191715131197531