मैं इस काल्पनिक उदाहरण को कैसे काम पर लाऊं?

newtype Q = Q [Int]

instance Arbitrary Q where
    arbitrary :: Gen Q
    arbitrary = do
        len <- choose (1, 5)
        pure $ g len (\ i -> i + choose (0, 1)) -- want different choice for each invocation

g :: Int -> (Int -> Int) -> Q -- g is a library function
g len f = Q $ fmap f [1 .. len]

यह संकलक त्रुटि देता है:

    * Couldn't match expected type `Int' with actual type `Gen a0'
    * In the second argument of `(+)', namely `choose (0, 1)'
      In the expression: i + choose (0, 1)
      In the second argument of `g', namely `(\ i -> i + choose (0, 1))'
0
puzzled 20 सितंबर 2019, 01:00

1 उत्तर

सबसे बढ़िया उत्तर

समस्या यह है कि choose (0, 1) एक Int का उत्पादन नहीं करता, यह एक Gen Int का उत्पादन करता है।

आप इसे इस तरह से व्यवहार कर रहे हैं जैसे कि यह इस अभिव्यक्ति में एक Int था:

pure $ g (\i -> i + choose (0, 1))

चूंकि Gen Int एक सन्यासी है, इसलिए आपको "पसंद" के परिणाम का उपयोग करने के लिए इसे बांधना होगा।

कुछ इस तरह:

instance Arbitrary Q where
    arbitrary :: Gen Q
    arbitrary = do
        choice <- choose (0, 1)
        return $ g (\i -> i + choice)

संपादित प्रश्न का उत्तर देना:

समस्या अभी भी वही है, आप Gen Int का उपयोग करने का प्रयास कर रहे हैं जैसे कि यह एक Int था। आप do के अंदर कई बार बाइंड कर सकते हैं।

यहाँ एक समाधान है:

instance Arbitrary Q where
    arbitrary :: Gen Q
    arbitrary = do
        len <- choose (1, 5)
        choice <- choose (0, 1)
        return $ g len (\i -> i + choice)

संपादित, संपादित प्रश्न का उत्तर:

आपको कहीं न कहीं दुष्प्रभावों का प्रचार करना होगा, इसका सीधा सा मतलब है कि आपको choose len बार दौड़ना होगा। क्योंकि g एक "लाइब्रेरी" फंक्शन है, मैं यह मानने जा रहा हूं कि इस पर आपका कोई नियंत्रण नहीं है, और मैं इसे बदल नहीं सकता। ध्यान दें कि नीचे दिया गया समाधान बदसूरत है क्योंकि मुझे आंशिक फ़ंक्शन (!!) का उपयोग करने की आवश्यकता है, और क्योंकि यह धीमा है (ऐसा करने का शायद एक बेहतर तरीका है, लेकिन मैं इसे ढूंढ नहीं पा रहा हूं)।

यहां ट्रिक यह है कि मैं एक फ़ंक्शन मैप कर रहा हूं जो len Gen Int लौटाता है, और फिर उन सभी को चलाता है, चुने हुए नंबरों की एक सूची तैयार करता है (देखें mapM विवरण के लिए विवरण)।

instance Arbitrary Q where
 arbitrary :: Gen Q
 arbitrary = do
     len <- choose (1, 5)
     choices <- mapM (\_ -> choose (0, 1)) [1 .. len]
     return $ g len (\i -> i + (choices !! i))
4
Neil Locketz 20 सितंबर 2019, 02:27