हसस्पेल कोड का यह टुकड़ा कैसे काम करता है?


91

Https://en.uncyclopedia.co/wiki/Haskell (और सभी "आक्रामक" सामानों को अनदेखा करते हुए) पढ़ते हुए , मैंने निम्न कोड के निम्न टुकड़े पर ठोकर खाई:

fix$(<$>)<$>(:)<*>((<$>((:[{- thor's mother -}])<$>))(=<<)<$>(*)<$>(*2))$1

जब मैं में कोड के उस टुकड़े को चलाने ghci(आयात करने के बाद Data.Functionऔर Control.Applicative), ghci2 की सभी शक्तियों की सूची प्रिंट करता है।

कोड का यह टुकड़ा कैसे काम करता है?


3
मुझे आश्चर्य है कि अगर जवाब कुछ आक्रामक रूप से अपमानजनक होगा ... अगर सच है, तो विडंबना यह है कि अश्लीलता से बचने के आपके प्रयासों पर विचार करें।
मेरेडिथ

31
आपने क्या प्रयास किया है? कोशिश करने वाली स्पष्ट चीजें हैं (ए) टिप्पणी को हटा दें, (बी) सुधारक / कोड को फिर से दर्ज करें, (सी) बाहर काम करें जो फ़ंक्टर / आवेदक / मोनाड के उदाहरणों का उपयोग किया जा रहा है (शायद सभी सूची, लेकिन मान नहीं है .. कुछ भी पर्याप्त रूप से नियोजित प्रोग्रामर को कोड की एक पंक्ति में मोनाड के पांच अलग-अलग उदाहरणों का उपयोग करने से नहीं रोक सकेगा), (डी) जितना संभव हो उतना सरल करें। फिर देखें कि आप किस चीज से बचे हैं।
dave4420

10
हास्केल मेरी पसंदीदा प्रोग्रामिंग भाषा है, अब तक, लेकिन फिर भी unyclopedia.wikia.com/wiki/Haskell ने मुझे बहुत हँसाया!
एंड्रयूज


5
यह वास्तव में मुझे गुस्सा दिलाता है जब कोई व्यक्ति सबसे गंभीर रूप से क्रिप्टिक कोड टुकड़ा पाता है जिसे वे भाषा XYZ में पा सकते हैं, और फिर इस तथ्य पर जोर देते हैं कि "भाषा XYZ में पठनीय कोड लिखना लगभग असंभव है"। लेकिन उस बस मुझे ... है
MathematicalOrchid

जवाबों:


219

शुरुआत करने के लिए, हमारे पास सुंदर परिभाषा है

x = 1 : map (2*) x

यदि आप पहले कभी इसे नहीं देखा है, जो अपने आप से थोड़ा सा झुकने वाला है। वैसे भी यह आलस्य और पुनरावृत्ति की काफी मानक चाल है। अब, हम स्पष्ट पुनरावर्तन का उपयोग करके fix, और बिंदु मुक्त-ify से छुटकारा पा लेंगे ।

x = fix (\vs -> 1 : map (2*) vs)
x = fix ((1:) . map (2*))

अगली चीज जो हम करने जा रहे हैं वह है :अनुभाग का विस्तार करना और mapअनावश्यक रूप से जटिल बनाना ।

x = fix ((:) 1 . (map . (*) . (*2)) 1)

खैर, अब हमारे पास उस स्थिरांक की दो प्रतियां हैं 1। ऐसा कभी नहीं होगा, इसलिए हम पाठक के आवेदन का उपयोग डी-डुप्लिकेट करने के लिए करेंगे। इसके अलावा, फंक्शन कंपोजिशन थोड़ा बकवास है, इसलिए (<$>)हम जहां चाहें वहां इसे बदल सकते हैं।

x = fix (liftA2 (.) (:) (map . (*) . (*2)) 1)
x = fix (((.) <$> (:) <*> (map . (*) . (*2))) 1)
x = fix (((<$>) <$> (:) <*> (map <$> (*) <$> (*2))) 1)

अगला: वह कॉल mapबहुत पठनीय है। लेकिन डरने की कोई बात नहीं है: हम इसे थोड़ा विस्तार देने के लिए मोनाद कानूनों का उपयोग कर सकते हैं। विशेष रूप से fmap f x = x >>= return . f, इसलिए

map f x = x >>= return . f
map f x = ((:[]) <$> f) =<< x

हम बिंदु-मुक्त-ify, के (.)साथ प्रतिस्थापित कर सकते हैं (<$>), और फिर कुछ सहज खंड जोड़ सकते हैं:

map = (=<<) . ((:[]) <$>)
map = (=<<) <$> ((:[]) <$>)
map = (<$> ((:[]) <$>)) (=<<)

इस समीकरण को हमारे पिछले चरण में प्रतिस्थापित करना:

x = fix (((<$>) <$> (:) <*> ((<$> ((:[]) <$>)) (=<<) <$> (*) <$> (*2))) 1)

अंत में, आप अपने स्पेसबार को तोड़ते हैं और अद्भुत अंतिम समीकरण उत्पन्न करते हैं

x=fix(((<$>)<$>(:)<*>((<$>((:[])<$>))(=<<)<$>(*)<$>(*2)))1)

4
आपने छोड़ दिया {- thor's mother -}!
सिमोन शाइन

14

अंतिम IR कोड के लिए मेरे IRC लॉग्स के पूर्ण रन-थ्रू के साथ एक लंबा उत्तर लिख रहा था (यह 2008 की शुरुआत में था), लेकिन मैं गलती से सभी पाठ :) नहीं है, हालांकि नुकसान का इतना - हालांकि अधिकांश भाग डैनियल के विश्लेषण पर हाजिर है।

यहाँ मैंने क्या शुरू किया है:

Jan 25 23:47:23 <olsner>        @pl let q = 2 : map (2*) q in q
Jan 25 23:47:23 <lambdabot>     fix ((2 :) . map (2 *))

मतभेद ज्यादातर उसी क्रम में आते हैं जिसमें रिफ्लेक्टरिंग हुई थी।

  • इसके बजाय x = 1 : map (2*) xमैंने शुरुआत की 2 : map ..., और मैंने उस शुरुआती 2 को बहुत अंतिम संस्करण तक सही रखा, जहां मैंने एक में निचोड़ा (*2)और $2अंत में बदल दिया $1। "नक्शे को अनावश्यक रूप से जटिल बनाएं" कदम ऐसा नहीं हुआ (जो कि शुरुआती हो)।
  • मैंने LifA2 की जगह LifM2 का इस्तेमाल किया
  • बाधा उत्पन्न हुई map समारोह अनुप्रयोगी combinators साथ liftM2 की जगह से पहले में रखा गया था। वह भी तब जब सभी स्थान गायब हो गए।
  • यहां तक ​​कि मेरे "अंतिम" संस्करण में .फ़ंक्शन रचना के लिए बहुत कुछ बचा था। <$>उस और अनसाइक्लोपीडिया के बीच के महीनों में स्पष्ट रूप से कुछ समय के साथ उन सभी को बदलना ।

BTW, यहाँ एक अद्यतन संस्करण है जो अब संख्या का उल्लेख नहीं करता है 2:

fix$(<$>)<$>(:)<*>((<$>((:[{- Jörð -}])<$>))(=<<)<$>(*)<$>(>>=)(+)($))$1

10
क्या पहले पैराग्राफ में "डिलीट" शब्द का जानबूझकर इस्तेमाल किया गया है? अगर ऐसा है तो मेरी टोपी आपको सर।
जेक ब्राउनसन

3
@JakeBrownson यह एक आम इंटरनेट मुहावरा है , हालांकि मुझे यकीन नहीं है कि यह उद्देश्य पर था।
लैम्ब्डा फेयरी

1

दोनों उत्तरों में नीले रंग से दिए गए छोटे मूल से ओब्सेक्टेड कोड स्निपेट मिलता है, लेकिन सवाल वास्तव में पूछता है कि लंबे ऑबफसकेटेड कोड अपना काम कैसे करते हैं।

ऐसे:

fix$(<$>)<$>(:)<*>((<$>((:[{- thor's mother -}])<$>))(=<<)<$>(*)<$>(*2))$1 
= {- add spaces, remove comment -}
fix $ (<$>) <$> (:) <*> ( (<$> ((:[]) <$>) ) (=<<)  <$>  (*)  <$>  (*2) ) $ 1 
--                      \__\______________/_____________________________/
= {-    A   <$> B   <*> C                          $ x   =   A (B x) (C x) -}
fix $ (<$>) (1 :)     ( ( (<$> ((:[]) <$>) ) (=<<)  <$>  (*)  <$>  (*2) ) 1 )
--                      \__\______________/____________________________/
= {- op f g = (f `op` g) ; (`op` g) f = (f `op` g) -}
fix $ (1 :) <$>  ( (((=<<) <$> ((:[]) <$>) )        <$>  (*)  <$>  (*2) ) 1 )
--                  \\____________________/____________________________/
= {- <$> is left associative anyway -}
fix $ (1 :) <$>  ( ( (=<<) <$> ((:[]) <$>)          <$>  (*)  <$>  (*2) ) 1 )
--                  \__________________________________________________/
= {- A <$> foo = A . foo when foo is a function -}
fix $ (1 :) <$>  ( ( (=<<) <$> ((:[]) <$>)           .   (*)   .   (*2) ) 1 )
--                  \__________________________________________________/
= {- ((:[]) <$>) = (<$>) (:[]) = fmap (:[])  is a function -}
fix $ (1 :) <$>  ( ( (=<<)  .  ((:[]) <$>)           .   (*)   .   (*2) ) 1 )
--                  \__________________________________________________/
= {- (a . b . c . d) x = a (b (c (d x))) -}
fix $ (1 :) <$>      (=<<)  (  ((:[]) <$>)           (   (*)   (   (*2)   1 )))
= {- (`op` y) x = (x `op` y) -}
fix $ (1 :) <$>      (=<<)  (  ((:[]) <$>)           (   (*)   2             ))
= {- op x = (x `op`) -}
fix $ (1 :) <$>      (=<<)  (  ((:[]) <$>)              (2*)                  )
= {-  (f `op`) g = (f `op` g) -}
fix $ (1 :) <$>      (=<<)  (   (:[]) <$>               (2*)                  )
= {-  A <$> foo = A . foo when foo is a function -}
fix $ (1 :) <$>      (=<<)  (   (:[])  .                (2*)                  )
= {-  (f . g) = (\ x -> f (g x)) -}
fix $ (1 :) <$>      (=<<)  (\ x -> [2*x]  )
= {- op f = (f `op`)  -}
fix $ (1 :) <$>           ( (\ x -> [2*x]  )  =<<)

यहाँ ( (\ x -> [2*x]) =<<) = (>>= (\ x -> [2*x])) = concatMap (\ x -> [2*x]) = map (2*)एक फ़ंक्शन है, इसलिए फिर से <$> = .:

= 
fix $ (1 :)  .  map (2*)
= {- substitute the definition of fix -}
let xs = (1 :) . map (2*) $ xs in xs
=
let xs = 1 : [ 2*x | x <- xs] in xs
= {- xs = 1 : ys -}
let ys =     [ 2*x | x <- 1:ys] in 1:ys
= {- ys = 2 : zs -}
let zs =     [ 2*x | x <- 2:zs] in 1:2:zs
= {- zs = 4 : ws -}
let ws =     [ 2*x | x <- 4:ws] in 1:2:4:ws
=
iterate (2*) 1
= 
[2^n | n <- [0..]]

बढ़ते क्रम में 2 की सभी शक्तियाँ हैं ।


यह उपयोग करता है

  • A <$> B <*> C $ x = liftA2 A B C xऔर चूंकि यह एक फ़ंक्शन पर liftA2 A B Cलागू होता है x, एक फ़ंक्शन के रूप में इसका मतलब है liftA2 A B C x = A (B x) (C x)
  • (f `op` g) = op f g = (f `op`) g = (`op` g) f ऑपरेटर वर्गों के तीन कानून हैं
  • >>=monadic बाइंड है, और चूंकि (`op` g) f = op f gऔर प्रकार हैं

    (>>=)                :: Monad m => m a -> (a -> m b ) -> m b
    (\ x -> [2*x])       :: Num t   =>         t -> [ t]
    (>>= (\ x -> [2*x])) :: Num t   => [ t]               -> [ t]

    प्रकार के आवेदन और प्रतिस्थापन द्वारा हम देखते हैं कि प्रश्न में मोनाड किसके []लिए है (>>= g) = concatMap g

  • concatMap (\ x -> [2*x]) xs के रूप में सरलीकृत किया गया है

    concat $ map (\ x -> [2*x]) 
    =
    concat $ [ [2*x] | x <- xs]
    =
             [  2*x  | x <- xs]
    =
             map (\ x ->  2*x )
  • और परिभाषा के अनुसार,

    (f . g) x  =  f (g x)
    
    fix f  =  let x = f x in x
    
    iterate f x  =  x : iterate f (f x)
                 =  x : let y = f x in 
                        y : iterate f (f y)
                 =  x : let y = f x in 
                        y : let z = f y in 
                            z : iterate f (f z)
                 = ...
                 = [ (f^n) x | n <- [0..]]

    कहाँ पे

            f^n  =  f  .  f  .  ...  . f
            --     \_____n_times _______/

    ताकि

    ((2*)^n) 1  =  ((2*) . (2*) .  ...  . (2*)) 1
                =    2*  (  2*  (  ...  (  2*   1 )...)) 
                =    2^n   ,  for n in [0..]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.