# Functional combinators for Scala List

Tail

def tail[A](l: List[A]): List[A] = l match {
case Nil => Nil
case h :: t => t
}


Drop

def drop[A](l: List[A], n: Int): List[A] = {
if (n <= 0) l
else l match {
case Nil => Nil
case _ :: t => drop(t, n - 1)
}
}


DropWhile

def dropWhile[A](l: List[A], f: A => Boolean): List[A] = l match {
case Nil => Nil
case h :: t => if (f(h)) dropWhile(t, f) else l
}


Curried DropWhile

def curriedDW[A](l: List[A])(f: A => Boolean): List[A] = l match {
case Nil => Nil
case h :: t => if (f(h)) curriedDW(t)(f) else l
}

val curry = curriedDW(List(1,2,3))_
// curry: (Int => Boolean) => List[Int] = <function1>

curriedDW(List(1,2,3,4,5))(x => x < 3)


Length

def length[A](l: List[A]): Int = l.foldRight(0){ (_, acc) => acc + 1}


Map

// using fold
def map[A,B](l: List[A])(f: A => B): List[B] = {
l.foldRight(List.empty[B]){ (x, acc) => f(x) :: acc }
}

// using pattern matching
def pmap[A,B](l: List[A])(f: A => B): List[B] = l match {
case Nil => Nil
case h :: t => f(h) :: pmap(t)(f)
}


Filter

// using fold
def filter[A](l: List[A])(f: A => Boolean): List[A] = {
l.foldRight(List.empty[A]){ (x, acc) => if (f(x)) x :: acc else Nil }
}

// using pattern matching
def pfilter[A](l: List[A])(f: A => Boolean): List[A] = l match {
case Nil => Nil
case h :: t => if (f(h)) h :: pfilter(t)(f) else pfilter(t)(f)
}

// using flatMap
def fmfilter[A](ls: List[A])(fn: A => Boolean): List[A] = {
ls.flatMap(x => if (fn(x)) List(x) else None)
}


flatMap

// using map and flatten
def flatMap[A,B](l: List[A])(f: (A => List[B])): List[B] = {
map(l)(f).flatten
}

// using pattern matching
def pflatMap[A,B](l: List[A])(f: (A => List[B])): List[B] = l match {
case Nil => Nil
case h :: t => f(h) ++ pflatMap(t)(f)
}

// using fold
def fflatMap[A,B](l: List[A])(f: (A => List[B])): List[B] = {
l.foldRight(List.empty[B]){ (x, acc) => f(x) ++ acc }
}


Fold

def foldLeft[A,B](ls: List[A])(z: B)(fn: (B, A) => B): B = {
var acc = z
ls foreach { x => acc = fn(acc, x) }
acc
}