我刚看了scala中的猫库,更具体地说是State Monad。
作为一个玩具示例,我想创建一些逻辑来分割一个可能很大的字符串(StringBuilder)并返回拆分的String和剩余的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机制在这里不起作用?
答案 0 :(得分:1)
修复SI-2712后,从{Cats:https://github.com/typelevel/cats/pull/1583中删除了Unapply
解决方法。现在您需要-Ypartial-unification
编译器标志(假设您使用的是Scala 2.11或2.12),以便将State
视为Monad
。
Scalaz仍然拥有Unapply
机制,因此您的代码应该在没有编译器标志的情况下使用Scalaz。