1

我在这里学习迈克尔·皮尔奎斯特(Michael Pilquist)的优秀状态单子讲座。我在 54 分钟时遇到了两个问题。

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

  2. 最后一个生成器如何将更新的缓存(增加命中或未命中)放回StatecheckCache 方法的结果中?返回的State似乎被丢弃了,而 for 理解似乎只产生了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理解,但这没有帮助。

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

更新: 由于答案,我想我已经掌握了第 2 点的关键。我没有意识到 yield 本质上是在说:从 中获取最后一个状态s => (s,())并用 ofsput替换Unit值类型,以获取s =>(s,ofs). 我想关键是要意识到收益并不是字面上的返回,而是被翻译为 State.map。

更新 现在了解选项位。我猜这个演示文稿仍然使用了 Scalaz 的隐式,尽管它派生了 state monad。

4

2 回答 2

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实际上是整个状态操作计算(在这种情况下,它不返回任何相关或有趣的值),包括更新。

于 2013-10-08T10:12:57.337 回答
1
  1. ?|运算符来自 scalaz 的布尔语法。看看这里 BooleanOps。它实际上是 2 个功能,首先?|Conditional.

  2. 更新的缓存实际上是运行State动作的结果。如果您在视频前面看,State应该被定义为,给定一个状态动作和一个初始状态s,运行状态动作并s导致 a(a, s2)是一对:(a)计算的值(表示a为元组)来自传入的状态和(b)动作执行后的新状态(表示为s2)。

请注意,直到通过一元动作运行Cache初始值才实际计算新值。Cache

于 2013-10-08T10:05:52.837 回答