代码之家  ›  专栏  ›  技术社区  ›  peri4n

对猫的状态激素进行测序

  •  1
  • peri4n  · 技术社区  · 7 年前

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

    1 回复  |  直到 7 年前
        1
  •  1
  •   Ziyang Liu    7 年前

    Unapply 从Cats中删除了解决方法: https://github.com/typelevel/cats/pull/1583 . 现在你需要 -Ypartial-unification 编译器标志(假设您使用的是Scala 2.11或2.12),以便 State 被视为 Monad

    Scalaz仍然拥有 不适用 因此,您的代码应该在没有编译器标志的情况下使用Scalaz。