我有一个用State monad包装的记录器的示例:
val logger = Logger(LoggerFactory.getLogger(this.getClass))
def logState[A](s:IO[Unit], a:A): State[List[IO[Unit]], A] = State[List[IO[Unit]], A]{ logs =>
(logs :+ s, a)
}
type Valid[A] = Exception \/ A
def i2f(i:Int): Valid[BigDecimal] = if (i >= 0) BigDecimal(i).right else (new RuntimeException("Input is smaller then 0")).left
def f2s(f: Valid[BigDecimal]): Valid[String] = f match {
case \/-(f1) => f1.toString.right
case -\/(e) => e.left
}
val comp: Int => State[List[IO[Unit]], Valid[String]] = i => for{
f <- logState(IO{ logger.info(s" => i2f($i)")}, i2f(i))
s <- logState(IO{ logger.info(s" => f2s($f)")}, f2s(f))
} yield s
comp(2)(List.empty) match {
case (logs, a) => {
logs.foreach(_.unsafePerformIO())
a match {
case \/-(s) => println(s"Finally we get: ${s}")
case -\/(e) => println(e.getMessage)
}
}
}
哪个工作得很好,但是我不满意添加State monad之前的代码,代码更加清楚了:
type Valid[A] = Exception \/ A
def i2f: Kleisli[Valid, Int, BigDecimal] = Kleisli { i =>
if (i >= 0) BigDecimal(i).right else (new RuntimeException("Input is smaller then 0")).left
}
def f2s: Kleisli[Valid, BigDecimal, String] = Kleisli { f =>
f.toString().right
}
def comp: Kleisli[Valid, Int, String] = i2f andThen f2s
comp(2) match {
case \/-(s) => println(s"Finally we get: ${s}")
case -\/(e) => println(e.getMessage)
}
我想知道如何让State与Kleisli合作?这样所有的monad都会像一个人一样工作?
logger
不能在i2f
和f2s
函数中起作用,但是还可以在其中工作吗?
答案 0 :(得分:0)
好吧,取得了一些进展,现在代码是:
page: (?<number>[0-9]+)
page: matches with "page: " literally.
(?<number> is the start of a named capture group called number. We can then use this group during replacement.
[0-9]+ matches a number between 0 and 9 one to infinite times. This is more specific than using \d as \d also matches other number characters.
The + makes it match more than on digit allowing for the number 10 and onwards.
) is the end of a named capture group.