ListOps.(span|break|partition|groupWhen|filter|takeWhile|takeUntil)M examples

77 views
Skip to first unread message

Chris Marshall

unread,
May 8, 2013, 7:05:09 AM5/8/13
to sca...@googlegroups.com
Can anyone give me some examples of the methods spanM, filterM, breakM etc?

Obviously there's the classic "powerset" implementation:

List('a, 'b, 'c) filterM (s => List(true, false))

But I personally find this difficult to have any intuition about. For example, what is going to happen if I use:

scala> val f: Int => Option[Boolean] = i => if (i % 3 == 0) None else Some(i % 2 == 0)
f: Int => Option[Boolean] = <function1>

And then call:

scala> List(1, 2, 3, 4) filterM f
scala> List(1, 2, 4) breakM f
scala> List(1, 2, 4) partitionM f

scala> List(1, 2, 3, 4) takeUntilM f
scala> List(3, 4) takeUntilM f

Obviously I've tried this and it has provided a little ilumination but I'd love to hear a great use of any of these functions

Chris








Jason Zaugg

unread,
May 8, 2013, 3:22:23 PM5/8/13
to sca...@googlegroups.com
On Wed, May 8, 2013 at 1:05 PM, Chris Marshall <oxbow...@gmail.com> wrote:
Can anyone give me some examples of the methods spanM, filterM, breakM etc?

Obviously there's the classic "powerset" implementation:

List('a, 'b, 'c) filterM (s => List(true, false))

But I personally find this difficult to have any intuition about. For example, what is going to happen if I use:

scala> val f: Int => Option[Boolean] = i => if (i % 3 == 0) None else Some(i % 2 == 0)
f: Int => Option[Boolean] = <function1>

The State monad fits very nicely into these. Here's an example the only retains the first of runs of the same element in a list:


-jason

Chris Marshall

unread,
May 9, 2013, 5:54:40 AM5/9/13
to sca...@googlegroups.com
Another great use, which I am struggling with just as much. For example, I have no idea what to expect were I to plug into spanM, breakM etc instead

Chris


--
You received this message because you are subscribed to the Google Groups "scalaz" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scalaz+un...@googlegroups.com.
To post to this group, send email to sca...@googlegroups.com.
Visit this group at http://groups.google.com/group/scalaz?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Jason Zaugg

unread,
May 9, 2013, 9:39:18 AM5/9/13
to sca...@googlegroups.com
On Thu, May 9, 2013 at 11:54 AM, Chris Marshall <oxbow...@gmail.com> wrote:
Another great use, which I am struggling with just as much. For example, I have no idea what to expect were I to plug into spanM, breakM etc instead

Just think what you could do with the regular span / break / etc, with an impure "function" as the argument.

// break into two sublists, the first one spanning elements >= the sum or prior elements.
scala> List(0, 1, 2, 3, 4).toList span {
  var sum = 0
  {x => 
    val r = (x >= sum)
    sum += x
    r
  }
}
res1: (List[Int], List[Int]) = (List(0, 1, 2, 3),List(4))

You can keep state to make the decision based on some state calculated with the previous elements, not just the current element.

spanM + the state monad offers a functional way to write this.

You can then do one-pass operations, rather than something like:

scala> val l = List(0, 1, 2, 3, 4)
l: List[Int] = List(0, 1, 2, 3, 4)

scala> val zipped = l zip l.inits.toList.reverse.map(_.sum)
zipped: List[(Int, Int)] = List((0,0), (1,0), (2,1), (3,3), (4,6))

scala> val (l1, l2) = zipped.span { case (x, prevSum) => x >= prevSum }
l1: List[(Int, Int)] = List((0,0), (1,0), (2,1), (3,3))
l2: List[(Int, Int)] = List((4,6))

scala> (l1.map(_._1), l2.map(_._1))
res1: (List[Int], List[Int]) = (List(0, 1, 2, 3),List(4))

-jason
Reply all
Reply to author
Forward
0 new messages