繁体   English   中英

斯卡拉州monad为了解

[英]Scala state monad in for comprehension

我学迈克尔Pilquist的出色状态单子讲座在这里 我被困在54分钟,有两个问题。

  1. 如果ofsOption[FollowerStats] ,那么它是? 运营商? 我在Scala 2.10.2中找不到Option上的三元运算符

  2. 最后一个生成器如何将更新的缓存(命中或未命中增加)放回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的值实际上是整个状态操纵计算(在这种情况下,一个不返回任何相关或有趣的值),包括更新。

  1. ?| 运算符来自scalaz的布尔语法。 看看BooleanOps 它实际上是2个功能,第一个? 然后| Conditional

  2. 更新的缓存实际上是运行State操作的结果。 如果你在视频的前面看一下, State应该被定义为一个东西,给定一个状态动作和一个初始状态s ,用s运行状态动作得到一个(a, s2) ,它是一对:(a)从传入状态计算的值(在元组中表示为a )和(b)在执行操作后的新状态(表示为s2 )。

请注意,在通过monadic动作运行初始Cache之前,实际上不会计算新的Cache

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM