我刚刚查看了scala的cats图书馆,更具体地说是State Monad。
作为一个玩具示例,我想创建一些逻辑来拆分一个潜在的大字符串(StringBuilder),并返回拆分后的字符串和剩余的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"))
然而,这不起作用,因为untilM是Monad trait的成员,并且范围中没有隐式转换。有效的方法是:
val monad = StateT.catsDataMonadForStateT[Eval, StringBuilder]
monad.untilM[List, String](Splitter(3, 2))(stop).run(new StringBuilder("tarsntiars"))
然而,我认为较短的更具可读性,所以我想知道为什么它不起作用?为什么通常的MonadOps机制在这里不起作用?