Last active
December 9, 2015 00:55
-
-
Save rjsen/57d42de5cb32d3c12670 to your computer and use it in GitHub Desktop.
Scala FP exercise
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This is a port of Tony Morris' Haskell beginner list exercises from (http://blog.tmorris.net/posts/haskell-beginner-exercises-with-tests/index.html). | |
To run, compile with `scalac Main.scala` and then run `scala Main`. | |
*/ | |
import scala.{List => _, :: => _, Nil => _} | |
sealed trait List[+T] { | |
def head: T | |
def tail: List[T] | |
def isEmpty: Boolean | |
def ::[U >: T](el: U): List[U] = new ::(el, this) | |
def foldLeft[U](init: U)(fun: (U, T) => U): U = this match { | |
case Nil => init | |
case x :: xs => xs.foldLeft(fun(init, x))(fun) | |
} | |
def foldRight[U](init: U)(fun: (T, U) => U): U = this match { | |
case Nil => init | |
case x :: xs => fun(x, xs.foldRight(init)(fun)) | |
} | |
def equals[U](that: List[U]): Boolean = { | |
(this.head == that.head) && (this.tail == that.tail) | |
} | |
/* | |
These are the functions to implement using the primitives defined above | |
*/ | |
def sum[U >: T](implicit num: Numeric[U]): U = ??? | |
def length: Int = ??? | |
def map[U](fun: T => U): List[U] = ??? | |
def filter(fun: T => Boolean): List[T] = ??? | |
def append[U >: T](that: List[U]): List[U] = ??? | |
def flatten[U](implicit ev: T => List[U]): List[U] = ??? | |
def flatMap[U](fun: T => List[U]): List[U] = ??? | |
def max[U >: T](implicit ord: Ordering[U]): Option[T] = ??? | |
def reverse: List[T] = ??? | |
} | |
case class ::[T](hd: T, tl: List[T]) extends List[T] { | |
override def head = hd | |
override def tail = tl | |
override def isEmpty = false | |
} | |
case object Nil extends List[Nothing] { | |
override def head = throw new NoSuchElementException("head on empty list") | |
override def tail = throw new UnsupportedOperationException("tail on empty list") | |
override def isEmpty = true | |
} | |
object List { | |
def apply[T](elems: T*): List[T] = { | |
if (elems.isEmpty) Nil else elems.head :: apply(elems.tail:_*) | |
} | |
} | |
object Main extends App { | |
println("running tests...") | |
val listNum = List(1,2,3,4) | |
assert(listNum.sum == 10, "sum") | |
assert(List[Int]().sum == 0, "sum") | |
assert(listNum.length == 4, "length") | |
assert(Nil.length == 0, "length") | |
assert(listNum.map(_ + 1) == List(2,3,4,5), "map") | |
assert(Nil.map(_.toString) == Nil, "map") | |
assert(listNum.filter(_ % 2 == 0) == List(2,4), "filter") | |
assert(Nil.filter(_ == 2) == Nil) | |
assert(listNum.append(List(5,6)) == List(1,2,3,4,5,6), "append") | |
assert(Nil.append(List(1,2)) == List(1,2), "append") | |
assert(List(List(1,2), List(3,4)).flatten == listNum, "flatten") | |
assert(Nil.flatten == Nil, "flatten") | |
assert(listNum.flatMap(x => List(x)) == listNum, "flatMap") | |
assert(Nil.flatMap(x => List(x)) == Nil, "flatMap") | |
assert(listNum.max.contains(4), "max") | |
assert(List[Int]().max.isEmpty, "max") | |
assert(listNum.reverse == List(4,3,2,1), "reverse") | |
assert(Nil.reverse == Nil, "reverse") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment