Skip to content

Instantly share code, notes, and snippets.

@rlmark
Created August 3, 2019 00:14
Show Gist options
  • Save rlmark/3367d6d0d382e354a512b9c727aa412e to your computer and use it in GitHub Desktop.
Save rlmark/3367d6d0d382e354a512b9c727aa412e to your computer and use it in GitHub Desktop.
Functional Programming in Scala Chapter 3 Part 1
import scala.annotation.tailrec
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 apply[A](as: A*): List[A] =
if (as.isEmpty) Nil
else Cons(as.head, apply(as.tail: _*))
def sum(ints: List[Int]): Int = ints match {
case Nil => 0
case Cons(h, tail) => h + sum(tail)
}
// Ex 3.1: answer is 3.
val x = List(1,2,3,4,5) match {
case Cons(x, Cons(2, Cons(4, _))) => x
case Nil => 42
case Cons(x: Int, Cons(y: Int, Cons(3, Cons(4, _)))) => x + y
case Cons(h: Int, t: List[Int]) => h + List.sum(t)
case _ => 101
}
// Ex 3.2
def tail[A](list: List[A]) = list match {
case Nil => Nil
case Cons(_, tail) => tail
}
// Ex 3.3
def setHead[A](newHead: A, list: List[A]): List[A] = {
list match {
case Cons(_, tail) => Cons(newHead, tail)
case Nil => Nil
}
}
// Ex 3.4
@tailrec
def drop[A](l: List[A], n: Int): List[A] = {
l match {
case Cons(_, tail) if n > 0 => drop(tail, n - 1)
case remainder => remainder
}
}
def dropWhile[A](l: List[A])(f: A => Boolean): List[A] = {
l match {
case Cons(head, tail) if f(head) => dropWhile(tail)(f)
case remainder => remainder
}
}
def init[A](l: List[A]): List[A] = {
l match {
case Cons(_, Nil) => Nil
case Cons(head, tail) => Cons(head, init(tail))
case Nil => Nil
}
}
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))
}
// Ex 3.7
// ProductR cannot short circuit
def productR(ns: List[Double]) = {
foldRight(ns, 1.0)(_ * _)
}
// Ex 3.8
val newList = foldRight(List(1,2,3), Nil : List[Int])((i, acc) => Cons(i,acc))
// Ex 3.9
def length[A](as: List[A]): Int = {
foldRight(as, 0)((_, acc) => acc + 1)
}
// Ex 3.10
def foldLeft[A,B](as: List[A], z: B)(f: (B, A) => B): B = {
as match {
case Nil => z
case Cons(head, tail) => foldLeft(tail, f(z, head))(f)
}
}
// Ex 3.11
def sumL(l: List[Int]): Int = {
foldLeft(l, 0)((acc, i) => acc + i )
}
def productL(l: List[Int]): Int = {
foldLeft(l, 1)(_ * _)
}
def lengthL[A](l: List[A]): Int = {
foldLeft(l, 0)((acc, _) => acc + 1)
}
// Ex 3.12
def reverseList[A](l: List[A]): List[A] = {
def loop(initial: List[A], acc: List[A]): List[A] = {
initial match {
case Nil => acc
case Cons(head, tail) => loop(tail, Cons(head, acc))
}
}
loop(l, Nil)
}
def reverseListFold[A](l: List[A]): List[A] = {
foldLeft(l, Nil: List[A])((acc, a) => Cons(a, acc))
}
}
println(List.x)
println(List.tail(List(1,2,3,4)))
println(List.setHead(100, List(1,2,3,4)))
println(List.drop(List(1,2,3,4), 2))
println(List.drop(List(1,2,3,4), 3))
println(List.drop(List(1,2,3,4), 4))
println(List.drop(List(1,2,3,4), 5))
println(List.drop(List(1,2,3,4), -5))
println(List.dropWhile(List(5,1,2,3,4))(_ % 2 == 0))
println(List.dropWhile(List(2,2,3,4))(_ % 2 == 0))
println(List.init(List(9,8,7,6,5,4,3,2,1)))
println(List.init(List(1)))
println(List.init(List()))
println(List.length(List(1)))
println(List.length(List(1,2,0)))
println(List.length(List()))
println(List.foldLeft(List(1,2,3), 1)(_ * _))
println(List.sumL(List(1,2,3,4)))
println(List.productL(List(5,5)))
println(List.lengthL(List(5,6,7)))
println(List.reverseList(List(1,2,3)))
println(List.reverseListFold(List(1,2,3)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment