2016-04-10 13 views
3

Ich bin auf der Suche nach einer Version von Generator-Kombinatoren (zB analog zu ScalaCheck oder Haskell's QuickCheck), in denen ein Generator eine Instanz von Rand enthält, eine Monade, die eine Wahrscheinlichkeitsverteilung darstellt die Brise-Bibliothek). Da es eine Monade ist, implementiert Rand map und flatMap. Wie üblich, möchte ich Gen auch als Monade implementieren. Wie unten gezeigt, ist die Umsetzung der Karte für Gen einfach:Implementierung von flatMap auf aggregate monad

// 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? 
    } 
} 

Es ist jedoch nicht klar für mich ist, wie flatMap umgesetzt werden sollten. Wird dies leicht erreicht, oder benötigt es (zum Beispiel) eine gewisse Umleitung über einen Zwischentyp?

Antwort

1

Eine mögliche Implementierung

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

die beabsichtigte Semantik von Gen etwas wie die folgenden sein könnte?

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

wo:

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

Wenn das stimmt, dann ist der Ausgang von Gen.flatMap muß entweder erzeugen zwei Stichproben, eine von jeder Verteilung oder Rand muss bietet eine Möglichkeit, die gemeinsame Verteilung zu berechnen und projizieren Sie es auf U.

Ich warf einen kurzen Blick auf die Dokumentation für Rand.flatMap, und es scheint, dass es eine Rand erzeugt, die die zwei aufeinanderfolgenden Stichproben durchführt, obwohl es nicht ganz klar ist. Wenn das stimmt, dann ist chi's answer Ihr Gewinner.

Wenn die beiden Zufallsvariablen nicht unabhängig sind, müssen Sie möglicherweise etwas arbeiten.

+0

Glücklicherweise ist die Unabhängigkeit die gewünschte Eigenschaft. – NietzscheanAI