3

我正在寻找实现生成器组合器的一个版本(例如,类似于 ScalaCheck 或 Haskell 的 QuickCheck 中的组合器),其中生成器包含 Rand 的一个实例,一个代表概率分布的单子(取自微风库)。由于是 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 应该如何实现。这很容易实现,还是(例如)需要通过一些中间数据类型进行间接级别?

4

2 回答 2

1

一个可能的实现可能是

def flatMap[U](f: T => Gen[U]): Gen[U] = 
  Gen (dist.flatMap {f(_).dist})
于 2016-04-10T16:45:42.943 回答
1

预期的语义是否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,它似乎生成了一个Rand执行两个连续随机样本的 a,尽管它并不完全清楚。如果这是正确的,那么chi 的答案就是你的赢家。

如果两个随机变量不是独立的,那么您可能需要做一些工作。

于 2016-04-10T18:58:52.303 回答