Ответ 1
def myFlatten[T](list : List[List[T]]) = for(xs <- list; x <- xs) yield x
Я пытаюсь реализовать свою собственную общую сглазку для объектов списка, которые хранят списки в Scala. На данный момент у меня есть
def myFlatten[T](list: List[List[t]]): List[T] = {
for (xs <- list)
for (x <- xs) yield x
}
Я получаю сообщение:
для xs found Требуемый блок.
def myFlatten[T](list : List[List[T]]) = for(xs <- list; x <- xs) yield x
Очень близко! Здесь один, который работает:
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]
Или используйте встроенный 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)
Поучительно видеть, как писать эту функцию без синтаксического сахара 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
Кстати, тот факт, что List[List[T]]
можно сгладить до List[T]
, составляет 50% от причины, что List
является Монадой. Как правило, это называется join
. Другие 50% исходят из того факта, что вы можете сопоставить функцию A => B
через a List[A]
, чтобы получить List[B]
. Общее имя для этого - Functor map
. fmap и присоединиться к Википедии.
Другой способ определения Monad для конструктора типов M
- это операция pure
, которая принимает значение типа A
и возвращает a M[A]
; и a bind
, которая принимает M[A]
, функцию A => M[B]
и приводит к M[B]
. Для списков pure
== List(_)
и bind
= (l: List[A], f: (A => List[B])) => l.flatMap(f)
Лично мне нравится этот стиль:
def myFlatten[T](list: List[List[t]]): List[T] = for {
xs <- list
x <- xs
} yield x