如何让State与Kleisli合作?

时间:2019-04-10 20:29:17

标签: scala monads monad-transformers state-monad kleisli

我有一个用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不能在i2ff2s函数中起作用,但是还可以在其中工作吗?

1 个答案:

答案 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.