2016-04-10 13 views
3

ジェネレータには確率分布を表すモナドであるジェネレータにジェネレータコンビネータ(ScalaCheckやHaskellのQuickCheckに類似したバージョン)を実装する予定です微風ライブラリー)。それはモナドなので、RandはmapとflatMapを実装します。よくあることですが、Genをモナドとして実装したいと考えています。以下に示すように、Genのマップの実装は簡単です:集計モナドでのflatMapの実装

// 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の実装方法はわかりません。これは簡単に達成できますか、それとも中間データ型を介して間接的なレベルを必要としますか?

答えて

1

可能な実装は

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

は、以下のようなGen何かの意図した意味論であるだろうか?そうです場合、Gen.flatMapの出力は同時分布を計算する方法を提供しなければならない2つのランダムサンプル、各ディストリビューションからの1、またはRandを生成する必要がありますどちらか

flipAndRoll == Gen(1 -> 0.025, 2 -> 0.025, 3 -> 0.025, 4 -> 0.025, 5 -> 0.45, 5 -> 0.45) 

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 _ } 

それをUに投影します。

Rand.flatMapのドキュメントを簡単に見て、完全にはっきりしていないが、2つの連続するランダムサンプルを生成するRandを生成するように見えます。そうなら、chi's answerがあなたの勝者です。

2つのランダム変数が独立していない場合、いくつかの作業が必要な場合があります。

+0

幸いにも、独立性が望ましい特性です。 – NietzscheanAI

関連する問題