Very close! Here's one that works:
scala> def myFlatten[T](list: List[List[T]]): List[T] = for (xs <- list; x <- xs) yield x
myFlatten: [T](list: List[List[T]])List[T]
Or use the built-in flatten
scala> List(List(1, 2), List(3)).flatten
res0: List[Int] = List(1, 2, 3)
scala> List(Set(1, 2), Set(3)).flatten
res1: List[Int] = List(1, 2, 3)
It's instructive to see how to write this function without the for
syntactic sugar.
scala> def myFlatten[T](list: List[List[T]]): List[T] = list flatMap identity
myFlatten: [T](list: List[List[T]])List[T]
scala> myFlatten(List(List(1, 2), List(3)))
res3: List[Int] = List(1, 2, 3)
UPDATE
BTW, the fact that List[List[T]]
can be flattened to List[T]
is 50% of the reason that List
is a Monad. Generally, this is known as join
. The other 50% comes from the fact you can map a function A => B
across a List[A]
to result in a List[B]
. The general name for this is a Functor map
. fmap and join on Wikipedia.
A different way of defining a Monad for type constructor M
is with a pure
operation, that takes a value of type A
, and returns a M[A]
; and a bind
operation that takes an M[A]
, a function A => M[B]
, and results in M[B]
. For Lists, pure
== List(_)
, and bind
= (l: List[A], f: (A => List[B])) => l.flatMap(f)