Question

I have three Scala regular expressions that I need to test to see if any of them matches a given String.

I know that I can do the following:

val matches = R1.findFirstIn(myString).isDefined ||
              R2.findFirstIn(myString).isDefined ||
              R3.findFirstIn(myString).isDefined

but I believe that there is a way to do this using an Applicative Functor or Monad from the Scalaz library.

How can this be done?

Was it helpful?

Solution

This is the sum under the "first" (or "last") monoid instance for Option. In Scalaz 7 you can write:

import scalaz._, Scalaz._

val R1 = "[a-c]".r
val R2 = "[d-f]".r
val R3 = "[g-i]".r

val m: Option[String] = List(R1, R2, R3).map(_.findFirstIn("test").first).suml

Or, alternatively:

val r1m = R1.findFirstIn("test").first
val r2m = R2.findFirstIn("test").first
val r3m = R3.findFirstIn("test").first

val m: Option[String] = r1m |+| r2m |+| r3m

Note that both of these solutions return the match itself, which you can of course call isDefined on if you want the same behavior as in your implementation.


As a side note, the |+| for the first monoid instance here is just orElse in the standard library, so you can write this almost as succinctly without Scalaz:

List(R1, R2, R3).map(_.findFirstIn("test")).reduce(_ orElse _)

Which is of course not an argument against using Scalaz, since it lets us capture the abstraction more cleanly, and provides an elegant way to change the behavior with regard to whether the first or last Some is returned.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top