2010-02-20 12 views
16

Sto cercando di implementare il mio appiattimento generico per gli oggetti lista che contengono liste in Scala. A questo punto hoCome posso ripetere un elenco di elenchi in Scala?

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

sto ottenendo un messaggio:

per XS trovati Lista Unità richiesto.

risposta

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

molto vicino! Ecco uno che funziona:

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 utilizzare il 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) 

E 'istruttivo vedere come scrivere questa funzione senza lo zucchero sintattico 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

proposito, il fatto che List[List[T]] può essere appiattito per List[T] è del 50% del motivo che List è una Monade. Generalmente, questo è noto come join. L'altro 50% deriva dal fatto che è possibile mappare una funzione A => B su uno List[A] in modo che risulti un List[B]. Il nome generale per questo è un Functor map. fmap and join on Wikipedia.

Un diverso modo di definire un Monade per tipo di costruzione è M con un'operazione pure, che assume un valore di tipo A, e restituisce una M[A]; e un'operazione bind che accetta uno M[A], una funzione A => M[B] e restituisce M[B]. Per le liste, pure == List(_), e bind = (l: List[A], f: (A => List[B])) => l.flatMap(f)

6

Personalmente, mi piace questo stile:

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