Created
August 3, 2019 00:14
-
-
Save rlmark/3367d6d0d382e354a512b9c727aa412e to your computer and use it in GitHub Desktop.
Functional Programming in Scala Chapter 3 Part 1
This file contains 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
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