Scala exercises for beginners

Scala exercises for beginnersを解いてみました。

import org.junit._
import org.junit.Assert._
import org.hamcrest.core.Is._

class EfB {
  def succ(n: Int) = n + 1
  def pred(n: Int) = n - 1
  //---------------------------------------------------------------------------
  @Test def Ex01 {
    assertThat(add(3, 7), is(10))
  }
  def add(x: Int, y: Int): Int = {
    x match {
      case 0 => y
      case _ => add(pred(x), succ(y))
    }
  }
  //---------------------------------------------------------------------------
  @Test def Ex02 {
    assertThat(sum(List(1, 1, 2, 3, 5, 8)), is(20))
  }
  def sum(ls: List[Int]): Int = {
    ls match {
      case Nil => 0
      case head :: tail => add(head, sum(tail))
    }
  }
  //---------------------------------------------------------------------------
  @Test def Ex03 {
    assertThat(length(List(1, 1, 2, 3, 5, 8)), is(6))
  }
  def length[T](ls: List[T]): Int = {
    ls match {
      case Nil => 0
      case _ :: tail => succ(length(tail))
    }
  }
  //---------------------------------------------------------------------------
  @Test def Ex04 {
    assertThat(map(List(1, 1, 2, 3, 5, 8), { (x: Int) => x.toString }),
      is(List("1", "1", "2", "3", "5", "8")))
  }
  def map[T, U](ls: List[T], f: T => U): List[U] = {
    ls match {
      case Nil => Nil
      case head :: tail => f(head) :: map(tail, f)
    }
  }
  //---------------------------------------------------------------------------
  @Test def Ex05 {
    assertThat(filter(List(1, 1, 2, 3, 5, 8), { (x: Int) => x % 2 == 0 }),
      is(List(2, 8)))
  }
  def filter[T](ls: List[T], pred: T => Boolean): List[T] = {
    ls match {
      case Nil => Nil
      case head :: tail if (pred(head)) => head :: filter(tail, pred)
      case _ :: tail => filter(tail, pred)
    }
  }
  //---------------------------------------------------------------------------
  @Test def Ex06 {
    assertThat(append(List(1, 1, 2), List(3, 5, 8)), is(List(1, 1, 2, 3, 5, 8)))
  }
  def append[T](xs: List[T], ys: List[T]): List[T] = {
    xs match {
      case Nil => ys
      case head :: tail => head :: append(tail, ys)
    }
  }
   //---------------------------------------------------------------------------
  @Test def Ex07 {
    assertThat(concat(List(List(1, 1), List(2), List(3, 5, 8))),
      is(List(1, 1, 2, 3, 5, 8)))
  }
  def concat[T](ls: List[List[T]]): List[T] = {
    ls match {
      case Nil => Nil
      case head :: tail => append(head, concat(tail))
    }
  }
  //---------------------------------------------------------------------------
  @Test def Ex08 {
    assertThat(concatMap(List(1, 1, 2, 3, 5, 8), { (x: Int) => List((x - 1).toString, x.toString) }),
      is(List("0", "1", "0", "1", "1", "2", "2", "3", "4", "5", "7", "8")))
  }
  def concatMap[T, U](ls: List[T], f: T => List[U]): List[U] = {
    ls match {
      case Nil => Nil 
      case head :: tail => append(f(head), concatMap(tail, f))
    }
  }
  //---------------------------------------------------------------------------
  @Test def Ex09 {
    assertThat(maximum(List(1, 5, 2, 8, 1, 3)), is(8))
  }
  def maximum(ls: List[Int]): Int = {
    ls match {
      case Nil => throw new IllegalArgumentException
      case head :: Nil => head
      case head :: tail if (maximum(tail) < head) => head
      case _ :: tail => maximum(tail)
    }
  }
  //---------------------------------------------------------------------------
  @Test def Ex10 {
    assertThat(reverse(List(1, 1, 2, 3, 5, 8)), is(List(8, 5, 3, 2, 1, 1)))
  }
  def reverse[T](ls: List[T]): List[T] = {
    ls match {
      case Nil => Nil
      case head :: tail => append(reverse(tail), List(head))
    }
  }
}