Использование состояния scalaz в более сложных вычислениях

Я пытаюсь понять, как использовать scalaz State ] для выполнения сложных вычислений с отслеживанием состояния. Вот проблема:

Учитывая Список [Int] потенциальных делителей и Список [Int] чисел, найдите ] Список [(Int, Int) ] совпадающих пар (делитель, число), где делителю разрешено совпадать не более одного числа.

В качестве теста:

def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)]

И с следующий ввод:

findMatches( List(2, 3, 4), List(1, 6, 7, 8, 9) )

Мы можем получить не более трех совпадений. Если мы оговорим, что совпадения должны выполняться в том порядке, в котором они происходят при обходе списков lr, тогда совпадения должны быть:

List( (2, 6) ,  (3, 9) , (4, 8) )

] Итак, следующие два теста должны пройти:

assert(findMatches(List(2, 3, 4), List(1, 6, 7, 8, 9)) == List((2, 6), (3, 9), (4, 8)))
assert(findMatches(List(2, 3, 4), List(1, 6, 7, 8, 11)) == List((2, 6),  (4, 8)))

Вот обязательное решение:

scala> def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)] = {
     |   var matches = List.empty[(Int, Int)]
     |   var remaining = nums
     |   divs foreach { div =>
     |     remaining find (_ % div == 0) foreach { n => 
     |       remaining = remaining filterNot (_ ==  n)
     |       matches = matches ::: List(div -> n) 
     |     }
     |   }
     |   matches
     | }
findMatches: (divs: List[Int], nums: List[Int])List[(Int, Int)]

Обратите внимание, что мне нужно обновить состояние оставшихся , а также накопить совпадений . звучит как работа для скалярного траверса!

Моя бесполезная работа завела меня так далеко:

scala> def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)] = {
     | divs.traverse[({type l[a] = State[List[Int], a]})#l, Int]( div =>
     | state { (rem: List[Int]) => rem.find(_ % div == 0).map(n => rem.filterNot(_ == n) -> List(div -> n)).getOrElse(rem -> List.empty[(Int, Int)]) }
     | ) ~> nums
     | }
<console>:15: error: type mismatch;
 found   : List[(Int, Int)]
 required: Int
       state { (rem: List[Int]) => rem.find(_ % div == 0).map(n => rem.filterNot(_ == n) -> List(div -> n)).getOrElse(rem -> List.empty[(Int, Int)]) }
                                                                                                                                       ^
16
задан oxbow_lakes 8 February 2012 в 13:18
поделиться