#scala #types #yield #for-comprehension
#scala #типы #выход #для понимания
Вопрос:
Я пишу функцию, которая будет принимать список вхождений символов ( List[(Char, Int)]
) в строке и создавать все подмножества этого списка вхождений.
Итак, учитывая
List(('a', 2), ('b', 2))
Это приведет к
List(
List(),
List(('a', 1)),
List(('a', 2)),
List(('b', 1)),
List(('a', 1), ('b', 1)),
List(('a', 2), ('b', 1)),
List(('b', 2)),
List(('a', 1), ('b', 2)),
List(('a', 2), ('b', 2))
)
Я реализовал это следующим образом:
type Occurrences = List[(Char, Int)]
def combinations(occurrences: Occurrences): List[Occurrences] =
if (occurrences.isEmpty) List(List())
else for {
(c, n) <- occurrences
i <- n to 1 by -1
} yield (c, i) :: combinations(occurrences.tail)
И я получаю эту ошибку:
type mismatch;
found : List[List[Product with Serializable]]
required: List[Occurrences]
(which expands to) List[List[(Char, Int)]]
Пожалуйста, помогите мне понять, почему это происходит, и как мне это исправить?
Я попытался переписать его как flatMap …, используя Intellij «Explain Scala code» и т.д.
Комментарии:
1. Какая-либо конкретная причина, которая мешает вам принять ответ?
Ответ №1:
На самом деле скобки отсутствуют:
type Occurrences = List[(Char, Int)]
def combinations(occurrences: Occurrences): List[Occurrences] =
if (occurrences.isEmpty) List(List())
else (for {
(c, n) <- occurrences
i <- n to 1 by -1
} yield (c, i)) :: combinations(occurrences.tail)
В вашем исходном коде для понимания пытались выдать, (c, i) :: combinations(occurrences.tail)
который List
имеет Any
элемент внутри ( Tuple
/ другой List
).
Обновить:
Правильный метод, который выполняет требуемую магию:
type Occurrences = List[(Char, Int)]
/**
* Returns the list of all subsets of the occurrence list.
* This includes the occurrence itself, i.e. `List(('k', 1), ('o', 1))`
* is a subset of `List(('k', 1), ('o', 1))`.
* It also include the empty subset `List()`.
*
* Example: the subsets of the occurrence list `List(('a', 2), ('b', 2))` are:
*
* List(
* List(),
* List(('a', 1)),
* List(('a', 2)),
* List(('b', 1)),
* List(('a', 1), ('b', 1)),
* List(('a', 2), ('b', 1)),
* List(('b', 2)),
* List(('a', 1), ('b', 2)),
* List(('a', 2), ('b', 2))
* )
*
* Note that the order of the occurrence list subsets does not matter -- the subsets
* in the example above could have been displayed in some other order.
*/
def combinations(occurrences: Occurrences): List[Occurrences] =
occurrences.foldRight(List[Occurrences](Nil)) {
case ((ltr, cnt), acc) =>
acc ::: (for {
comb <- acc
ltrNum <- 1 to cnt
} yield (ltr, ltrNum) :: comb)
}
Вся слава автору этого кода.
Комментарии:
1. Круглые скобки определяют тип, но изменяют предполагаемое поведение кода. Я пытаюсь получить точно
(c, i) :: combinations(occurrences.tail)
2. Давайте разберем это:
combinations(occurrences.tail)
имеет типList[List[(Char, Int)]]
. Вы пытаетесь добавить,(c, i)
что есть(Char, Int)
. Вы должны добавитьList[(Char, Int)]
3. Однако даже после этого это не дает требуемого результата, что заставляет меня думать, что сам алгоритм не совсем корректен. Я не собираюсь публиковать решение алгоритмической проблемы, поскольку ваш вопрос требует решения проблемы компиляции.
4. Пожалуйста, ознакомьтесь с обновлением, оно содержит метод, который делает то, что вам нужно.