Соответствие по крайней мере 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
возвращается