在猫中对 StateMonad 进行测序
Sequencing a StateMonad in Cats
我刚刚查看了 scala 中的猫库,更具体地说是 State Monad。
作为玩具示例,我想创建一些逻辑来拆分可能较大的字符串(StringBuilder)和 returns 拆分字符串和剩余的 StringBuilder:
object Splitter {
def apply(maxSize: Int, overlap: Int): State[StringBuilder, String] = State(
builder => {
val splitPoint = math.min(builder.size, maxSize + overlap)
(builder.drop(maxSize), builder.substring(0, splitPoint))
}
)
}
运行 State monad 的一个步骤工作正常,但我想链接所有步骤,直到 StringBuilder 最终为空:
val stop = State.inspect((s: StringBuilder) => s.isEmpty)
Splitter(3, 2).untilM[Vector](stop).run(new StringBuilder("tarsntiars"))
但是,这不起作用,因为直到 M 是 Monad 特征的成员并且范围内没有隐式转换。有效的是:
val monad = StateT.catsDataMonadForStateT[Eval, StringBuilder]
monad.untilM[List, String](Splitter(3, 2))(stop).run(new StringBuilder("tarsntiars"))
但是,我认为较短的版本更具可读性,所以我想知道为什么它不起作用?为什么通常的 MonadOps 机制在这里不起作用?
修复 SI-2712 后,Unapply
解决方法已从 Cats 中移除:https://github.com/typelevel/cats/pull/1583。现在您需要 -Ypartial-unification
编译器标志(假设您使用的是 Scala 2.11 或 2.12),以便 State
被视为 Monad
.
Scalaz 仍然具有 Unapply
机制,因此您的代码应该可以在没有编译器标志的情况下使用 Scalaz。
我刚刚查看了 scala 中的猫库,更具体地说是 State Monad。
作为玩具示例,我想创建一些逻辑来拆分可能较大的字符串(StringBuilder)和 returns 拆分字符串和剩余的 StringBuilder:
object Splitter {
def apply(maxSize: Int, overlap: Int): State[StringBuilder, String] = State(
builder => {
val splitPoint = math.min(builder.size, maxSize + overlap)
(builder.drop(maxSize), builder.substring(0, splitPoint))
}
)
}
运行 State monad 的一个步骤工作正常,但我想链接所有步骤,直到 StringBuilder 最终为空:
val stop = State.inspect((s: StringBuilder) => s.isEmpty)
Splitter(3, 2).untilM[Vector](stop).run(new StringBuilder("tarsntiars"))
但是,这不起作用,因为直到 M 是 Monad 特征的成员并且范围内没有隐式转换。有效的是:
val monad = StateT.catsDataMonadForStateT[Eval, StringBuilder]
monad.untilM[List, String](Splitter(3, 2))(stop).run(new StringBuilder("tarsntiars"))
但是,我认为较短的版本更具可读性,所以我想知道为什么它不起作用?为什么通常的 MonadOps 机制在这里不起作用?
修复 SI-2712 后,Unapply
解决方法已从 Cats 中移除:https://github.com/typelevel/cats/pull/1583。现在您需要 -Ypartial-unification
编译器标志(假设您使用的是 Scala 2.11 或 2.12),以便 State
被视为 Monad
.
Scalaz 仍然具有 Unapply
机制,因此您的代码应该可以在没有编译器标志的情况下使用 Scalaz。