MyList - step 4
Foreach, Map and Filter
Exercise
Add the following methods to MyList
- foreach
- map
- filter
trait MyList[A]:
...
def foreach(f: A => B): Unit
def map[B](f: A => B): MyList[B]
def filter(f: A => Boolean): MyList[A]
Solution Foreach
Empty
override def foreach(f: A => Unit): Unit = ()
Should return Unit. The implementation of Unit is ()
Cons
override def foreach(f: A => Unit): Unit =
f(head)
tail.foreach(f)
We have to walk through the linked list get the call the function on the head
and then jump to the tail recursively.
Solution Map
Empty
override def map[B](f: A => B): MyList[B] = Empty[B]()
Transforming an empty list of type A gives us an empty list of type B.
This feels a weird. That because of our definition Empty
If we had it defined as:
case object Empty extends MyList[Nothing]
But then we have implement a covariant/contravariant version op the type A. That is something for the advanced course.
You could leave out the type on the Cons because the compiler know the type from the return type MyList[B]
Empty()
Cons
override def map[B](f: A => B): MyList[B] =
Cons[B](f(head), tail.map(f))
We have to walk through the linked list of type A
call the function on the head
and walk the tail recursively.
And wrap inside a new Cons of type B
You could leave out the type on the Cons because the compiler know the type from the return type MyList[B]
Cons(f(head), tail.map(f))
Solution Filter
Empty
override def filter[B](f: A => Boolean): MyList[A] = this
Filtering an empty list gives an empty list.
Cons
override def filter[B](f: A => Boolean): MyList[A] =
if !f(head) then
tail.filter(f)
else
Cons(head, tail.filter(f))
We check if the predicate f on the head is false then we go further on filtering the tail
If the predicate f is true then the head is added to new Cons, and then we go further on the filtering the tail
main
@main
def main(): Unit =
val myList: MyList[Int] = MyList(1,2,3)
myList.foreach(x => println(x + 2))
println(myList.map(x => x * 2))
println(myList.filter(x => x < 2))
// 3
// 4
// 5
// MyList(2, 4, 6)
// MyList(1)