在聚合 monad 上实现 flatMap
Implementing flatMap on aggregate monad
我正在寻求实现一个版本的生成器组合器(例如类似于 ScalaCheck 或 Haskell 的 QuickCheck 中的组合器),其中生成器包含 Rand 的一个实例,一个表示概率分布的单子(取自 breeze 库)。由于是 monad,Rand 实现了 map 和 flatMap。通常,我也想将 Gen 实现为 monad。如下图,Gen的map实现很简单:
// Rand is from the breeze library
trait Rand[T] {
def map[U](f: T => U): Rand[U]
def flatMap[U](f: T => Rand[U]): Rand[U]
}
case class Gen[T](dist: Rand[T]) {
def map[U](f: T => U): Gen[U] = Gen(dist.map { f })
def flatMap[U](f: T => Gen[U]): Gen[U] = {
// How to implement this?
}
}
但是,我不清楚 flatMap 应该如何实现。这很容易实现,还是(例如)需要通过某种中间数据类型进行一定程度的间接访问?
可能的实施方式是
def flatMap[U](f: T => Gen[U]): Gen[U] =
Gen (dist.flatMap {f(_).dist})
Gen
的预期语义是否类似于以下内容?
val UnfairCoin = Gen(Rand(Heads -> 0.9, Tails -> 0.1))
val UnfairDieHi = Gen(Rand(1 -> 0.0, 2 -> 0.0, 3 -> 0.0, 4 -> 0.0, 5 -> 0.5. 6 -> 0.5))
val UnfairDieLo = Gen(Rand(1 -> 0.25, 2 -> 0.25, 3 -> 0.25, 4 -> 0.25, 5 -> 0.0, 6 -> 0.0))
def headsHiTailsLo(coinFlip: CoinFlip) = coinFlip match {
case Heads => UnfairDieHi
case Tails => UnfairDieLo
}
val flipAndRoll = UnfairCoin flatMap { headsHighTailsLo _ }
其中:
flipAndRoll == Gen(1 -> 0.025, 2 -> 0.025, 3 -> 0.025, 4 -> 0.025, 5 -> 0.45, 5 -> 0.45)
如果这是正确的,那么 Gen.flatMap
的输出将需要生成两个随机样本,每个样本来自每个分布,或者 Rand
必须提供一种计算联合分布并将其投影的方法至 U
.
我快速浏览了 Rand.flatMap
, and it appears that it generates a Rand
that does the two consecutive random samples, although it's not entirely clear. If that's right, then 的文档。
如果这两个随机变量不是独立的,那么您可能需要做一些工作。
我正在寻求实现一个版本的生成器组合器(例如类似于 ScalaCheck 或 Haskell 的 QuickCheck 中的组合器),其中生成器包含 Rand 的一个实例,一个表示概率分布的单子(取自 breeze 库)。由于是 monad,Rand 实现了 map 和 flatMap。通常,我也想将 Gen 实现为 monad。如下图,Gen的map实现很简单:
// Rand is from the breeze library
trait Rand[T] {
def map[U](f: T => U): Rand[U]
def flatMap[U](f: T => Rand[U]): Rand[U]
}
case class Gen[T](dist: Rand[T]) {
def map[U](f: T => U): Gen[U] = Gen(dist.map { f })
def flatMap[U](f: T => Gen[U]): Gen[U] = {
// How to implement this?
}
}
但是,我不清楚 flatMap 应该如何实现。这很容易实现,还是(例如)需要通过某种中间数据类型进行一定程度的间接访问?
可能的实施方式是
def flatMap[U](f: T => Gen[U]): Gen[U] =
Gen (dist.flatMap {f(_).dist})
Gen
的预期语义是否类似于以下内容?
val UnfairCoin = Gen(Rand(Heads -> 0.9, Tails -> 0.1))
val UnfairDieHi = Gen(Rand(1 -> 0.0, 2 -> 0.0, 3 -> 0.0, 4 -> 0.0, 5 -> 0.5. 6 -> 0.5))
val UnfairDieLo = Gen(Rand(1 -> 0.25, 2 -> 0.25, 3 -> 0.25, 4 -> 0.25, 5 -> 0.0, 6 -> 0.0))
def headsHiTailsLo(coinFlip: CoinFlip) = coinFlip match {
case Heads => UnfairDieHi
case Tails => UnfairDieLo
}
val flipAndRoll = UnfairCoin flatMap { headsHighTailsLo _ }
其中:
flipAndRoll == Gen(1 -> 0.025, 2 -> 0.025, 3 -> 0.025, 4 -> 0.025, 5 -> 0.45, 5 -> 0.45)
如果这是正确的,那么 Gen.flatMap
的输出将需要生成两个随机样本,每个样本来自每个分布,或者 Rand
必须提供一种计算联合分布并将其投影的方法至 U
.
我快速浏览了 Rand.flatMap
, and it appears that it generates a Rand
that does the two consecutive random samples, although it's not entirely clear. If that's right, then
如果这两个随机变量不是独立的,那么您可能需要做一些工作。