Ich gehe durch Learn You A Haskell und habe gerade den Teil "Für ein paar Monaden mehr" abgeschlossen. In diesem Teil haben wir eine newtype Prob a = Prob { getProb :: [(a, Rational)] }
erstellt und eine Monad
Instanz dafür erstellt. Dies erlaubt uns, Wahrscheinlichkeiten der Ergebnisse in nicht-deterministischen Berechnungen zu berechnen wie folgt aus:Haskell - Zusammenfassende Wahrscheinlichkeitsliste
data Coin = Heads | Tails deriving (Show, Eq)
coin :: Prob Coin
coin = Prob [(Heads, 1%2), (Tails, 1%2)]
loadedCoin :: Prob Coin
loadedCoin = Prob [(Heads, 1%10), (Tails, 9%10)]
coinTest :: Prob Bool
coinTest = do
a <- coin
b <- coin
c <- loadedCoin
return (all (==Tails) [a,b,c])
Natürlich ist dies nicht erzeugt ein sehr schönes Ergebnis:
getProb coinTest
>> [(False,1 % 40),(False,9 % 40),(False,1 % 40),(False,9 % 40),(False,1 % 40),(False,9 % 40),(False,1 % 40),(True,9 % 40)]
Es wurde als Übung an den Leser, um eine ordentliche Funktion zu schreiben, um alle False
s und alle True
s zusammenzufassen, so erhalten wir [(True,9 % 40),(False,31 % 40)]
. Ich habe es irgendwie geschafft. Es funktioniert für diesen speziellen Fall, aber ich habe das Gefühl, dass es überhaupt keine nützliche Funktion ist, da es so spezialisiert ist. Hier ist, was ich kam mit:
sumProbs :: Prob Bool -> Prob Bool
sumProbs (Prob ps) = let (trues, falses) = partition fst ps
ptrue = reduce trues
pfalse = reduce falses
in Prob [ptrue, pfalse]
where reduce = foldr1 (\(b,r) (_,r') -> (b,r+r'))
Ich würde es lieben, zu verallgemeinern für jeden Eq a => Prob a
zu arbeiten, aber bisher kein Glück. Ich dachte daran, vielleicht eine Map
zusammen mit unionWith
oder etwas ähnliches zu verwenden. Oder kann ich die Tatsache ausnutzen, dass eine Functor b
Instanz hat? Ich denke, ich vermisse eine einfachere, elegantere Lösung.
Also, um es zusammenzufassen: Wie kann ich eine Funktion schreiben sumProbs :: (Eq a) => Prob a -> Prob a
, die alle Wahrscheinlichkeiten zusammenfasst, die den gleichen Wert (Schlüssel) teilen?
Ah ja, das ist sehr sauber. Ich nehme an, der Nachteil ist, dass dies eine 'Ord'-Einschränkung für a erfordert, während die andere Lösung mit' Eq 'arbeitet (ich denke, dass' sortBy 'unnötig ist). – kai
@Kai 'groupBy' wird _nicht_ gruppiert, wenn die gleichwertigen Schlüssel nicht nebeneinander liegen (versuche' group [1, 2, 1] '). also ist das 'sortBy' notwendig –
Oh, naja das erledigt es dann! Ich nehme an, das ist aus Leistungsgründen? – kai