2015-07-29 9 views
5

मैं दो जेनरेटर, gen_n & gen_arr हैक्विक चेक: दो जेनरेटर कैसे गठबंधन करें?

gen_n :: Gen Int 
gen_n = suchThat arbitrary (\i -> i >= 0 && i <= 10) 

gen_elem :: Gen Int 
gen_elem = suchThat arbitrary (\i -> i >= 0 && i <= 100) 

gen_arr :: Gen [Int] 
gen_arr = listOf gen_elem 

मैं कैसे इन दो एक Gen (Int, [Int]) में गठजोड़ कर सकते हैं?

combine_two_gens :: Gen a -> Gen b -> Gen (a, b) 

उत्तर

7

(i) आप उन्हें गठबंधन करने के लिए सामान्य functorial/monadic रचना का उपयोग कर सकते हैं: (बेशक, Control.Applicative.liftA2 और Control.Monad.liftM2 भी ठीक हैं)

gen_comb :: Gen (Int, [Int]) 
gen_comb = (,) <$> gen_elem <*> gen_arr 

(ii) केवल एक सीमा को रोकने के लिए suchThat का उपयोग न करें। यह बहुत अक्षम हो सकता है, क्योंकि यह स्थिति याद होने तक यादृच्छिक उदाहरण उत्पन्न करता है, बाकी को छोड़ देता है। इसके बजाय, आप elements :: [a] -> Gen a इस्तेमाल कर सकते हैं:

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]) 

अद्यतन: जीटा जैसा कि नीचे टिप्पणी की, हम और भी बेहतर इस मामले में choose (0,100) (choose :: Random a => (a, a) -> Gen a) का उपयोग करके elements [0..100] के बजाय कर सकते हैं। जेनरेटर संयोजकों की पूरी सूची के लिए here, या 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 बनाम elements:

*Main> sample (suchThat arbitrary (\i -> i >= 10000 && i <= 10005)) 
^CInterrupted. 
*Main> sample (elements [10000..10005]) 
10003 
10002 
10000 
10000 
... 

suchThat जनरेटर उत्पादन कुछ भी नहीं किया।

+2

'तत्वों के बजाय' (0,100) 'चुनें [0..100]'। जबकि 'तत्व' बहुत बढ़िया है यदि आपकी सीमा निरंतर नहीं है या यदि आपके प्रकार में 'रैंडम' उदाहरण नहीं है, तो 'मान' आमतौर पर अधिक कुशल होता है यदि आपके मान बंद सीमा में हैं। – Zeta

संबंधित मुद्दे