(i) Sie normale funktoriellen/monadischen Zusammensetzung, sie kombinieren können:
gen_comb :: Gen (Int, [Int])
gen_comb = (,) <$> gen_elem <*> gen_arr
(Control.Applicative.liftA2
und Control.Monad.liftM2
auch fein sind, natürlich)
(ii) Verwenden Sie suchThat
nicht, um nur einen Bereich zu beschränken. Es kann furchtbar ineffizient sein, da es nur zufällige Instanzen generiert, bis die Bedingung erfüllt ist, und den Rest verwerfen. Stattdessen könnten Sie elements :: [a] -> Gen a
verwenden:
gen_elem' :: Gen Int
gen_elem' = elements [0..100]
gen_arr' :: Gen [Int]
gen_arr' = listOf gen_elem'
gen_comb' :: Gen (Int, [Int])
gen_comb' = (,) <$> elements [0..100] <*> listOf (elements [0..100])
Update: Wie Zeta unten bemerkt, können wir es besser machen, auch in diesem Fall durch choose (0,100)
(choose :: Random a => (a, a) -> Gen a
) statt elements [0..100]
verwenden. Eine vollständige Liste der Generatorkombinatoren finden Sie unter here oder here.
*Main> sample gen_arr'
[78]
[2,27]
[12,39]
[92,22,40,6,18,19,25,13,95,99]
...
*Main> sample gen_comb'
(9,[23,3])
(11,[67,38,11,79])
(5,[96,69,68,81,75,14,59,68])
...
suchThat
gegen elements
:
*Main> sample (suchThat arbitrary (\i -> i >= 10000 && i <= 10005))
^CInterrupted.
*Main> sample (elements [10000..10005])
10003
10002
10000
10000
...
Der suchThat
Generator aber keine Ausgabe nichts.
Betrachten Sie 'wählen (0,100)' anstelle von 'Elemente [0..100]'. Während 'elements' groß sind, wenn Ihr Bereich nicht kontinuierlich ist oder wenn Ihr Typ keine' Random'-Instanz hat, ist 'choose' normalerweise effizienter, wenn sich Ihre Werte in einem geschlossenen Bereich befinden. – Zeta