Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing scalaz state in a more complicated computation
    primarykey
    data
    text
    <p>I'm trying to understand how to use scalaz <code>State</code> to perform a complicated stateful computation. Here is the problem:</p> <blockquote> <p>Given a <code>List[Int]</code> of potential divisors and a <code>List[Int]</code> of numbers, find a <code>List[(Int, Int)</code>] of matching pairs (divisor, number) where a divisor is allowed to match <em>at most one</em> number.</p> </blockquote> <p>As a test:</p> <pre><code>def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)] </code></pre> <p>And with the following input:</p> <pre><code>findMatches( List(2, 3, 4), List(1, 6, 7, 8, 9) ) </code></pre> <p>We can get at most 3 matches. If we stipulate that the matches must be made in the order in which they occur traversing the lists l-r, then the matches <em>must</em> be:</p> <pre><code>List( (2, 6) , (3, 9) , (4, 8) ) </code></pre> <p>So the following two tests need to pass:</p> <pre><code>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))) </code></pre> <p>Here's an imperative solution:</p> <pre><code>scala&gt; def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)] = { | var matches = List.empty[(Int, Int)] | var remaining = nums | divs foreach { div =&gt; | remaining find (_ % div == 0) foreach { n =&gt; | remaining = remaining filterNot (_ == n) | matches = matches ::: List(div -&gt; n) | } | } | matches | } findMatches: (divs: List[Int], nums: List[Int])List[(Int, Int)] </code></pre> <p>Notice that I have to update the state of <code>remaining</code> as well as accumulating <code>matches</code>. It sounds like a job for scalaz traverse!</p> <p>My useless working has got me this far:</p> <pre><code>scala&gt; def findMatches(divs: List[Int], nums: List[Int]): List[(Int, Int)] = { | divs.traverse[({type l[a] = State[List[Int], a]})#l, Int]( div =&gt; | state { (rem: List[Int]) =&gt; rem.find(_ % div == 0).map(n =&gt; rem.filterNot(_ == n) -&gt; List(div -&gt; n)).getOrElse(rem -&gt; List.empty[(Int, Int)]) } | ) ~&gt; nums | } &lt;console&gt;:15: error: type mismatch; found : List[(Int, Int)] required: Int state { (rem: List[Int]) =&gt; rem.find(_ % div == 0).map(n =&gt; rem.filterNot(_ == n) -&gt; List(div -&gt; n)).getOrElse(rem -&gt; List.empty[(Int, Int)]) } ^ </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload