斯卡拉州monad为了解

时间:2013-10-08 09:42:28

标签: scala monads scalaz state-monad

我正在研究迈克尔·皮尔奎斯特出色的州议会演讲here。我被困在54分钟,有两个问题。

  1. 如果ofsOption[FollowerStats],那么?运算符是什么?一世 在Scala 2.10.2

  2. 中找不到Option上的三元运算符
  3. 最后一个生成器如何将更新的缓存(命中或未命中增加)放回checkCache方法的State结果中?返回的State似乎被丢弃,而理解似乎只能产生Option[FollowerStats]

  4. def checkCache(u: String): State[Cache, Option[FollowerState]] = for {
        c <- State.get[Cache]
        ofs <- State.state {
            c.get(u).collect {
                case Timestamped(fs, ts) if !state(ts) => fs
            }
        }
        _ <- State.put(ofs ? c.recordHit | c.recordMiss)
    } yield ofs
    

    试图理解我试图重新编写for comprehension,但它没有帮助。

    State.get[Cache].flatMap{ c => 
        State.state{c.get(u).collect(...)}.flatMap{ ofs =>
            State.put(ofs ? c.recordHit | c.recordMiss).map{ _ =>
                ofs
            }
        }
    }
    

    更新 由于答案,我认为我已经掌握了第2点的关键。我没有意识到收益率基本上是这样说:从s => (s,())获取最后一个状态put并将Unit值类型替换为ofs,以获得s =>(s,ofs)。我想关键是要意识到产量不是字面上的返回,但它被翻译为State.map。

    更新 现在了解选项。我猜这个演示文稿仍然使用Scalaz的含义,尽管它衍生出状态monad。

2 个答案:

答案 0 :(得分:2)

首先是三元运算符。

ofs ? c.recordHit | c.recordMiss

相当于:

if (ofs.isDefined) c.recordHit else c.recordMiss

或者:

ofs.fold(c.recordMiss)(_ => c.recordHit)

它由Scalaz提供,并作为隐式类(OptionOps)实现,为?提供Option方法,返回Conditional类,其| }} 方法。在这种情况下,我不确定额外的简洁是否值得混淆,但人们使用它,所以值得了解。

对于状态更新,请考虑以下简化示例:

val inc: State[Int, Unit] = for { i <- get[Int]; _ <- put(i + 1) } yield ()

它可能首先看起来像我们“丢弃”状态并且仅产生单位,但inc的值实际上是整个状态操纵计算(在这种情况下,一个不返回任何相关或有趣的价值),包括更新。

答案 1 :(得分:1)

  1. ?|运算符来自scalaz的布尔语法。看看here at BooleanOps。它实际上是2个函数,?上的|然后Conditional

  2. 更新的缓存实际上是运行State操作的结果。如果您在视频的前面看到,State应该被定义为在给定状态操作和初始状态s的情况下,使用s运行状态操作会导致{(a, s2) 1}}这是一对:(a)从传入状态计算的值(在元组中表示为a)和(b)在执行操作后的新状态(表示为{{ 1}})。

  3. 请注意,在通过monadic动作运行初始s2之前,实际上并未计算新的Cache