gpt4 book ai didi

scala - 在更复杂的计算中使用 scalaz 状态

转载 作者:行者123 更新时间:2023-12-03 14:53:34 25 4
gpt4 key购买 nike

我试图了解如何使用 scalaz State执行复杂的有状态计算。这是问题所在:

Given a List[Int] of potential divisors and a List[Int] of numbers, find a List[(Int, Int)] of matching pairs (divisor, number) where a divisor is allowed to match at most one number.



作为测试:
def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)]

并使用以下输入:
findMatches( List(2, 3, 4), List(1, 6, 7, 8, 9) )

我们最多可以得到 3 场比赛。如果我们规定匹配必须按照它们遍历列表 l-r 的顺序进行,那么匹配必须是:
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)]

请注意,我必须更新 remaining 的状态以及积累 matches .这听起来像是 scalaz traverse 的工作!

我无用的工作让我走到了这一步:
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)]) }
^

最佳答案

您的代码只需要稍微修改即可使用 State 和 Traverse:

// using scalaz-seven
import scalaz._
import Scalaz._

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

// the "state" we carry when traversing
case class S(matches: List[(Int, Int)], remaining: List[Int])

// initially there are no found pairs and a full list of nums
val initialState = S(List[(Int, Int)](), nums)

// a function to find a pair (div, num) given the current "state"
// we return a state transition that modifies the state
def find(div: Int) = modify((s: S) =>
s.remaining.find(_ % div == 0).map { (n: Int) =>
S(s.matches :+ div -> n, s.remaining -n)
}.getOrElse(s))

// the traversal, with no type annotation thanks to Scalaz7
// Note that we use `exec` to get the final state
// instead of `eval` that would just give us a List[Unit].
divs.traverseS(find).exec(initialState).matches
}

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

您也可以使用 runTraverseS以不同的方式编写遍历:
 divs.runTraverseS(initialState)(find)._2.matches

关于scala - 在更复杂的计算中使用 scalaz 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9193826/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com