DarkOtter की टिप्पणी QuickCheck के Arbitrary
और CoArbitrary
कक्षाएं, जो निश्चित रूप से पहली बात का प्रयास करना चाहिए रहे हैं उल्लेख है। मैं तो बस कल QuickCheck कोड को पढ़ने समझने के लिए यह कैसे काम करता था, इसलिए मैं सिर्फ साझा कर सकते हैं कि मैं क्या सीखा, जबकि यह मेरे मन में ताजा है कि ऐसा होता है
instance (CoArbitrary a, Arbitrary b) => Arbitrary (a -> b) where ...
,: QuickCheck इस उदाहरण है। QuickCheck एक प्रकार है कि इस तरह दिखता है आसपास बनाया गया है (और यह बिल्कुल वैसा ही नहीं होगा):
type Size = Int
-- | A generator for random values of type @[email protected]
newtype Gen a =
MkGen { -- | Generate a random @[email protected] using the given randomness source and
-- size.
unGen :: StdGen -> Size -> a
}
class Arbitrary a where
arbitrary :: a -> Gen a
पहले चाल कि QuickCheck एक समारोह है कि इस तरह काम करता है (और मैं ऐसा नहीं हो पाया यह वास्तव में कैसे लागू हो जाता है):
-- | Use the given 'Int' to \"perturb\" the generator, i.e., to make a new
-- generator that produces different pseudorandom results than the original.
variant :: Int -> Gen a -> Gen a
तब वे इस का उपयोग इस CoArbitrary
वर्ग के विभिन्न उदाहरणों को लागू करने:
class CoArbitrary a where
-- | Use the given `a` to perturb some generator.
coarbitrary :: a -> Gen b -> Gen b
-- Example instance: we just treat each 'Bool' value as an 'Int' to perturb with.
instance CoArbitrary Bool where
coarbitrary False = variant 0
coarbitrary True = variant 1
जगह में इन टुकड़ों के साथ
अब, हम इस हैं:
instance (Coarbitrary a, Arbitrary b) => Arbitrary (a -> b) where
arbitrary = ...
मैं कार्यान्वयन लिख नहीं होगा, लेकिन विचार यह है:
a
की CoArbitrary
उदाहरण और b
की Arbitrary
उदाहरण का उपयोग करते हुए हम समारोह \a -> coarbitrary a arbitrary
, टाइप है जो कर सकते हैं a -> Gen b
।
- याद रखें कि
Gen b
StdGen -> Size -> b
के लिए एक नया प्रकार है, इसलिए a -> Gen b
a -> StdGen -> Size -> b
पर isomorphic है।
- हम उस फ़ंक्शन को छोटे से लिख सकते हैं जो उस बाद के प्रकार का कोई भी फ़ंक्शन लेता है और
StdGen -> Size -> a -> b
प्रकार के फ़ंक्शन को वापस करने के लिए तर्क ऑर्डर को स्विच करता है।
- यह पुनर्नवीनीकरण प्रकार
Gen (a -> b)
पर isomorphic है, इसलिए voilà, हम पुनर्नवीनीकरण फ़ंक्शन को Gen
में पैक करते हैं, और हमें हमारे यादृच्छिक फ़ंक्शन जेनरेटर मिलते हैं!
मैं अनुशंसा करता हूं कि आप इसे अपने लिए देखने के लिए क्विक चेक के स्रोत को पढ़ लें। जब आप इससे निपटते हैं, तो आप केवल दो अतिरिक्त विवरणों में भागने जा रहे हैं जो आपको धीमा कर सकते हैं। सबसे पहले, हास्केल RandomGen
वर्ग इस विधि है:
-- | The split operation allows one to obtain two distinct random generators.
split :: RandomGen g => g -> (g, g)
इस आपरेशन Gen
के लिए Monad
उदाहरण में प्रयोग किया जाता है, और नहीं बल्कि महत्वपूर्ण है। यहां चालों में से एक यह है कि StdGen
एक शुद्ध छद्म यादृच्छिक संख्या जनरेटर है; जिस तरह से Gen (a -> b)
काम करता है कि a
के प्रत्येक संभावित मूल्य के लिए हम b
जनरेटर को परेशान करते हैं, b
परिणाम उत्पन्न करने के लिए उस परेशान जनरेटर का उपयोग करें, लेकिन फिर हम परेशान जनरेटर के राज्य को कभी भी अग्रिम नहीं करते; मूल रूप से जेनरेट a -> b
फ़ंक्शन एक छद्म-यादृच्छिक बीज पर बंद होता है, और हर बार जब हम इसे a
के साथ कॉल करते हैं तो हम निश्चित रूप से एक नया बीज बनाने के लिए उस विशिष्ट a
का उपयोग करते हैं, और फिर b
को निर्धारित करने के लिए इसका उपयोग करें जो a
पर निर्भर करता है और छिपी हुई बीज
संक्षिप्त प्रकार Seed -> a -> b
कम या ज्यादा रकम ऊपर क्या हो रहा है पर एक छद्म यादृच्छिक समारोह एक छद्म यादृच्छिक बीज से एक b
और एक a
पैदा करने के लिए एक नियम है। यह अनिवार्य शैली के राज्यव्यापी यादृच्छिक संख्या जेनरेटर के साथ काम नहीं करेगा।
दूसरा: ऊपर वर्णित अनुसार (a -> StdGen -> Size -> b) -> StdGen -> Size -> a -> b
फ़ंक्शन के बजाय, क्विक चेक कोड में promote :: Monad m => m (Gen a) -> Gen (m a)
है, जो कि Monad
पर इसका सामान्यीकरण है। जब m
Monad
का फ़ंक्शन उदाहरण है, promote
(a -> Gen b) -> Gen (a -> b)
के साथ मेल खाता है, तो यह वास्तव में वही है जैसा मैं ऊपर स्केच करता हूं।
पूरी तरह से मूल्यांकन किए जाने पर, क्या सभी कार्यों का एक ही परिणाम प्रकार होगा? – mhwombat
@mhwombat हां, वे करेंगे। – Eyal
कार्यों के क्या परिणाम और तर्क प्रकार होना चाहिए?उदाहरण के लिए क्विक चेक में मनमानी और सहकारी कक्षाओं को देखने के लायक हो सकते हैं, जिनका प्रयोग परीक्षण उद्देश्यों के लिए यादृच्छिक रूप से कार्यों को उत्पन्न करने के लिए किया जाता है। इसके अलावा, यदि आपको वास्तव में टाइपशेकर को बाईपास करने की आवश्यकता है, तो आप इसे असुरक्षित वाणिज्य का उपयोग करके कर सकते हैं। यह वास्तव में टाइप करने योग्य के कास्ट फ़ंक्शन में आंतरिक रूप से उपयोग किया जाता है। – DarkOtter