मोनो-ट्रैवर्सेबल से "कॉनकटैब" कैसे आम तर्क को "बाहर निकालने" में सक्षम है?


9

मैं हास्केल सीख रहा हूं और यसोद के लिए एक साधारण डीबी-बीज कार्यक्रम कर रहा था जब मैं इस व्यवहार पर ठोकर खाई, जो मुझे लगता है:

testFn :: Int -> Bool -> [Int]
testFn a b = if b then replicate 10 a else []

Yesod GHCI सत्र:

$ :t concatMap testFn [3]
concatMap testFn [3] :: Bool -> [Int]
$ (concatMap testFn [1,2,3]) True
[1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3]

किसी तरह एक मैप किए गए तर्क में प्रत्येक मैपिंग से उस दूसरे "बूल" को "बाहर" निकालने में सक्षम था।

मानक बेस प्रस्तावना GHCI सत्र इस अभिव्यक्ति को संकलित करने से भी इनकार करता है:

$ :t concatMap testFn [3]
error:
     Couldn't match type 'Bool -> [Int]' with '[b]'
      Expected type: Int -> [b]
        Actual type: Int -> Bool -> [Int]
     Probable cause: 'testFn' is applied to too few arguments
      In the first argument of 'concatMap', namely 'testFn'
      In the expression: concatMap testFn [3]

Yesod ने मोनो-ट्रैवर्सेबल लाइब्रेरी का उपयोग किया है जिसका अपना है concatMap:

$ :t concatMap
concatMap
  :: (MonoFoldable mono, Monoid m) =>
     (Element mono -> m) -> mono -> m

हास्केल समझ के मेरे मौजूदा स्तर पर मैं यह पता नहीं लगा सका कि यहां प्रकार कैसे वितरित किए जाते हैं। क्या कोई मुझे समझा सकता है (जितना संभव हो उतना शुरुआती उन्मुख) यह चाल कैसे होती है? testFnऊपर का भाग किस Element monoप्रकार के अनुरूप है ?

जवाबों:


6

हम कुछ प्रकारों को सूचीबद्ध करके शुरू करते हैं जिन्हें हम जानते हैं। (हम दिखावा करते हैं कि संख्या Intसादगी के लिए है - यह वास्तव में प्रासंगिक नहीं है।)

testFn :: Int -> Bool -> [Int]
[1,2,3] :: [Int]
True :: Bool

(concatMap testFn [1,2,3]) Trueसमान है concatMap testFn [1,2,3] True, इसलिए concatMapउन सभी तर्कों से मेल खाने वाला एक प्रकार होना चाहिए:

concatMap :: (Int -> Bool -> [Int]) -> [Int] -> Bool -> ???

???परिणाम प्रकार कहां है ध्यान दें कि, समतुल्यता नियमों के कारण, ->दाईं ओर सहयोगी होता है, इसलिए उपरोक्त टाइपिंग निम्नानुसार है:

concatMap :: (Int -> (Bool -> [Int])) -> [Int] -> (Bool -> ???)

आइए उस एक के ऊपर सामान्य प्रकार लिखें। मैं समानता को चिह्नित करने के लिए कुछ स्थान जोड़ रहा हूं।

concatMap :: (MonoFoldable mono, Monoid m) =>
             (Element mono -> m              ) -> mono  -> m
concatMap :: (Int          -> (Bool -> [Int])) -> [Int] -> (Bool -> ???)

आह-हा! अगर हम चुनें हम एक मैच mके रूप में Bool -> [Int], और monoके रूप में [Int]। यदि हम ऐसा करते हैं, तो हम बाधाओं MonoFoldable mono, Monoid m(नीचे देखें) को संतुष्ट करते हैं, और हमारे पास भी है Element mono ~ Int, इसलिए सब कुछ जांचता है।

हम अनुमान कर कि ???है [Int]की परिभाषा से m

बाधाओं के बारे में: MonoFoldable [Int]कहने के लिए बहुत कम है। [Int]एक Intतत्व प्रकार के साथ स्पष्ट रूप से एक सूची- प्रकार है, और यह इसके MonaFoldableसाथ एक के Intरूप में बनाने के लिए पर्याप्त है Element

इसके लिए Monoid (Bool -> [Int]), यह थोड़ा अधिक जटिल है। हमारे पास यह है कि कोई भी फ़ंक्शन प्रकार A -> Bएक मोनॉइड है यदि Bएक मोनॉइड है। यह एक पॉइंटवाइज़ फैशन में ऑपरेशन करने के बाद होता है। हमारे विशिष्ट मामले में, हम [Int]एक भिक्षु होने पर भरोसा करते हैं और हमें मिलता है:

mempty :: Bool -> [Int]
mempty = \_ -> []

(<>) :: (Bool -> [Int]) -> (Bool -> [Int]) -> (Bool -> [Int])
f <> g = \b -> f b ++ g b

1
महान व्याख्या! जिस तरह से आपने समझाया और संरेखित प्रकार है बस वही है जो मैं देखना चाहता था, धन्यवाद!
डिसूज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.