在更复杂的计算中使用scalaz状态
发布时间:2020-12-16 09:32:12 所属栏目:安全 来源:网络整理
导读:我正在努力了解如何使用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 on
我正在努力了解如何使用scalaz State执行复杂的有状态计算。这是问题:
作为测试: 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,9)) == List((2,8))) assert(findMatches(List(2,11)) == List((2,8))) 这是一个迫在眉睫的解决方案: scala> def findMatches(divs: 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],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,8)) findMatches(List(2,9)) 您也可以使用runTraverseS来写入遍历方式: divs.runTraverseS(initialState)(find)._2.matches (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |