Соответствие по крайней мере 1 из 3 регулярных выражений Scala с использованием аппликативного функтора

У меня есть три регулярных выражения Scala, которые мне нужно проверить, чтобы убедиться, что любое из них соответствует заданной строке.

Я знаю, что могу сделать следующее:

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

но я считаю, что есть способ сделать это, используя Applicative Functor или Monad из библиотеки Scalaz.

Как это может быть сделано?

1 ответ

Решение

Это сумма в "первом" (или "последнем") экземпляре моноида для Option, В Scalaz 7 вы можете написать:

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

Или, альтернативно:

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

Обратите внимание, что оба эти решения возвращают само совпадение, которое вы, конечно, можете назвать isDefined если вы хотите того же поведения, что и в вашей реализации.


Как примечание стороны, |+| для первого экземпляра моноида здесь просто orElse в стандартной библиотеке, так что вы можете написать это почти так же кратко без Scalaz:

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

Что, конечно, не является аргументом против использования Scalaz, поскольку оно позволяет нам более четко фиксировать абстракцию и предоставляет элегантный способ изменить поведение в отношении того, является ли первый или последний Some возвращается

Другие вопросы по тегам