2010-02-20 13 views
16

Próbuję zaimplementować własne generyczne spłaszczanie dla obiektów listy, które przechowują listy w Scali. W tym momencie mamJak mogę powtórzyć listę list w Scali?

def myFlatten[T](list: List[List[t]]): List[T] = { 
    for (xs <- list) 
     for (x <- xs) yield x 
} 

Otrzymuję wiadomość:

dla xs znaleziono wymaganego Jednostka listę.

Odpowiedz

23
def myFlatten[T](list : List[List[T]]) = for(xs <- list; x <- xs) yield x 
12

Bardzo blisko! Oto ten, który działa:

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] 

też użyć wbudowanego 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) 

To pouczające, aby zobaczyć, jak napisać tę funkcję bez cukru składniowej for.

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

okazji, fakt, że List[List[T]] mogą być spłaszczone do List[T] 50% z powodu List jest monady. Zasadniczo jest to znane jako join. Pozostałe 50% pochodzi z faktu, że możesz odwzorować funkcję A => B na List[A], aby uzyskać List[B]. Ogólna nazwa tego to Functor map. fmap and join on Wikipedia.

inny sposób definiowania monadę dla typu konstruktora M jest z pure działania, które ma wartość typu A i zwraca M[A]; oraz operację bind, która zajmuje M[A], funkcję , i daje w wyniku M[B]. Na listach pure == List(_) i bind = (l: List[A], f: (A => List[B])) => l.flatMap(f)

6

Osobiście lubię ten styl:

def myFlatten[T](list: List[List[t]]): List[T] = for { 
    xs <- list 
    x <- xs 
} yield x