在Cats中对StateMonad进行排序

时间:2017-10-12 04:38:11

标签: scala state-monad scala-cats

我刚看了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机制在这里不起作用?

1 个答案:

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