2010-02-20 28 views
16

Estoy tratando de implementar mi propio aplanamiento genérico para objetos de lista que contienen listas en Scala. En este punto tengo¿Cómo puedo iterar una lista de listas en Scala?

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

estoy recibiendo un mensaje:

para XS encontrado Lista Unidad requerida.

Respuesta

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

Muy cerca! Aquí hay una que funciona:

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] 

O utilizar el incorporado en 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) 

Es instructivo ver cómo escribir esta función sin el azúcar sintáctica 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) 

ACTUALIZACIÓN

Por cierto, el hecho de que List[List[T]] puede aplanarse a List[T] es 50% de la razón de que List es una Mónada. En general, esto se conoce como join. El otro 50% proviene del hecho de que puede asignar una función A => B a través de List[A] para generar un List[B]. El nombre general para esto es Functor map. fmap and join on Wikipedia.

Una forma diferente de la definición de una Mónada para el tipo constructor M es con una operación de pure, que toma un valor de tipo A, y devuelve un M[A]; y una operación bind que toma un M[A], una función A => M[B], y da como resultado M[B]. Por Listas, pure == List(_) y bind = (l: List[A], f: (A => List[B])) => l.flatMap(f)

6

Personalmente, me gusta este estilo:

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