【问题标题】:Implementing flatMap on aggregate monad在聚合单子上实现 flatMap
【发布时间】:2016-07-31 15:41:59
【问题描述】:

我希望实现一个生成器组合器版本(例如,类似于 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 应该如何实现。这很容易实现,还是(例如)需要通过某种中间数据类型实现一定程度的间接性?

【问题讨论】:

    标签: scala haskell monads scala-breeze


    【解决方案1】:

    一个可能的实现可能是

    def flatMap[U](f: T => Gen[U]): Gen[U] = 
      Gen (dist.flatMap {f(_).dist})
    

    【讨论】:

      【解决方案2】:

      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,它会执行两个连续的随机样本,尽管它并不完全清楚。如果没错,那么chi's answer 就是你的赢家。

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

      【讨论】:

      • 幸运的是,独立性是理想的属性。
      猜你喜欢
      • 1970-01-01
      • 2018-08-16
      • 1970-01-01
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      • 1970-01-01
      • 2011-04-05
      • 1970-01-01
      相关资源
      最近更新 更多