[英]Scala state monad in for comprehension
我学迈克尔Pilquist的出色状态单子讲座在这里 。 我被困在54分钟,有两个问题。
如果ofs
是Option[FollowerStats]
,那么它是?
运营商? 我在Scala 2.10.2中找不到Option上的三元运算符
最后一个生成器如何将更新的缓存(命中或未命中增加)放回checkCache方法的State
结果中? 返回的State
似乎被丢弃,而理解似乎只能产生Option[FollowerStats]
。
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点的关键。 我没有意识到收益率基本上是说:从put
取最后一个状态s => (s,())
并用ofs替换Unit
值类型,得到s =>(s,ofs)
。 我想关键是要意识到收益率不是字面上的返回,但它被翻译为State.map。
更新立即了解选项位。 我猜这个演示文稿仍然使用Scalaz的含义,尽管它衍生出状态monad。
首先是三元运算符。
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
的值实际上是整个状态操纵计算(在这种情况下,一个不返回任何相关或有趣的值),包括更新。
?|
运算符来自scalaz的布尔语法。 看看BooleanOps 。 它实际上是2个功能,第一个?
然后|
在Conditional
。
更新的缓存实际上是运行State
操作的结果。 如果你在视频的前面看一下, State
应该被定义为一个东西,给定一个状态动作和一个初始状态s
,用s
运行状态动作得到一个(a, s2)
,它是一对:(a)从传入状态计算的值(在元组中表示为a
)和(b)在执行操作后的新状态(表示为s2
)。
请注意,在通过monadic动作运行初始Cache
之前,实际上不会计算新的Cache
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.