खोज…


परिचय

एक मोनाड एक डेटा प्रकार की रचना करने योग्य क्रिया है। Monad प्रकार के Monad का वर्ग है, जिनके मूल्य ऐसे कार्यों का प्रतिनिधित्व करते हैं। शायद IO सबसे ज्यादा पहचाने जाने योग्य है: IO a का a मूल्य "वास्तविक दुनिया से मूल्य प्राप्त करने के लिए एक नुस्खा है"।

हम कहते हैं कि एक टाइप कंस्ट्रक्टर m (जैसे [] या Maybe ) एक मोनड बनाता है यदि एक instance Monad m कुछ क्रियाओं की रचना के बारे में कुछ कानूनों को संतोषजनक करता है। फिर हम ma बारे में एक "कार्रवाई जिसका परिणाम प्रकार a " के रूप में कारण कर सकते हैं।

शायद मोनाड

Maybe संभवतः खाली मूल्यों का प्रतिनिधित्व करने के लिए उपयोग किया जाता है - अन्य भाषाओं में null समान। आमतौर पर इसका उपयोग आउटपुट प्रकार के कार्यों के रूप में किया जाता है जो किसी तरह से विफल हो सकते हैं।

निम्नलिखित कार्य पर विचार करें:

halve :: Int -> Maybe Int
halve x
  | even x = Just (x `div` 2)
  | odd x  = Nothing

एक Int आधार पर एक कार्रवाई के रूप में halve बारे में सोचें, जो पूर्णांक को आधा करने की कोशिश करता है, अगर यह अजीब है तो विफल।

हम एक पूर्णांक को तीन बार halve कैसे करते हैं?

takeOneEighth :: Int -> Maybe Int            -- (after you read the 'do' sub-section:)
takeOneEighth x =                
  case halve x of                               --  do {
    Nothing -> Nothing
    Just oneHalf ->                             --     oneHalf    <- halve x
      case halve oneHalf of
        Nothing -> Nothing
        Just oneQuarter ->                      --     oneQuarter <- halve oneHalf
          case halve oneQuarter of
            Nothing -> Nothing                  --     oneEighth  <- halve oneQuarter
            Just oneEighth ->                         
              Just oneEighth                    --     return oneEighth }
  • takeOneEighth तीन का क्रम है halve एक साथ श्रृंखलित चरणों।
  • एक तो halve कदम विफल रहता है, हम पूरी रचना चाहते takeOneEighth विफल।
  • यदि एक halve कदम सफल होता है, तो हम इसके परिणाम को आगे बढ़ाना चाहते हैं।

instance Monad Maybe where
  -- (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
  Nothing >>= f  = Nothing                            -- infixl 1 >>=
  Just x  >>= f  = Just (f x)                         -- also, f =<< m = m >>= f
  
  -- return :: a -> Maybe a
  return x       = Just x

और अब हम लिख सकते हैं:

takeOneEighth :: Int -> Maybe Int
takeOneEighth x = halve x >>= halve >>= halve             -- or,
    -- return x >>= halve >>= halve >>= halve             -- which is parsed as
    -- (((return x) >>= halve) >>= halve) >>= halve       -- which can also be written as
    -- (halve =<<) . (halve =<<) . (halve =<<) $ return x    -- or, equivalently, as
    --  halve <=<     halve <=<     halve      $        x

क्लेस्ली रचना <=< के रूप में परिभाषित किया गया है (g <=< f) x = g =<< fx , या समकक्ष के रूप में (f >=> g) x = fx >>= g । इसके साथ उपरोक्त परिभाषा बस बन जाती है

takeOneEighth :: Int -> Maybe Int
takeOneEighth = halve <=< halve <=< halve               -- infixr 1 <=<
        -- or, equivalently,                    
        --      halve >=> halve >=> halve               -- infixr 1 >=>    

तीन इकाई कानून है कि हर इकाई द्वारा पालन किया जाना चाहिए रहे हैं, कि हर प्रकार के जो का एक उदाहरण है है Monad typeclass:

1.  return x >>= f  =  f x
2.    m >>= return  =  m
3. (m >>= g) >>= h  =  m >>= (\y -> g y >>= h)

जहाँ m एक मोनड है, f में टाइप a -> mb और g है टाइप b -> mc

या समकक्ष, ऊपर परिभाषित >=> क्लेसीली रचना ऑपरेटर का उपयोग करते हुए:

1.    return >=> g  =  g                    -- do { y <- return x ; g y } == g x
2.    f >=> return  =  f                    -- do { y <- f x ; return y } == f x
3. (f >=> g) >=> h  =  f >=> (g >=> h)      -- do { z <- do { y <- f x; g y } ; h z }
                                            --  == do { y <- f x ; do { z <- g y; h z } }

इन कानूनों का पालन करना मठ के बारे में तर्क करना बहुत आसान बनाता है, क्योंकि यह गारंटी देता है कि अन्य मठों के समान ही, मठ के कार्यों का उपयोग करना और उनका उचित तरीके से व्यवहार करना।

आइए देखें कि क्या Maybe मोनद तीन मानद कानूनों का पालन करता है।

  1. बाईं पहचान विधि - return x >>= f = fx
return z >>= f 
= (Just z) >>= f 
= f z
  1. सही पहचान कानून - m >>= return = m
  • Just डेटा कंस्ट्रक्टर
Just z >>= return
= return z
= Just z  
  • Nothing डेटा कंस्ट्रक्टर नहीं
Nothing >>= return
= Nothing 
  1. संबद्धता कानून - (m >>= f) >>= g = m >>= (\x -> fx >>= g)
  • Just डेटा कंस्ट्रक्टर
-- Left-hand side
((Just z) >>= f) >>= g
= f z >>= g

-- Right-hand side
(Just z) >>= (\x -> f x >>= g)
(\x -> f x >>= g) z
= f z >>= g
  • Nothing डेटा कंस्ट्रक्टर नहीं
-- Left-hand side
(Nothing >>= f) >>= g
= Nothing >>= g
= Nothing

-- Right-hand side
Nothing >>= (\x -> f x >>= g)
= Nothing

आईओ मोनाद

प्रकार का एक मूल्य प्राप्त करने का कोई तरीका नहीं है a प्रकार की अभिव्यक्ति से बाहर IO a और वहाँ नहीं होना चाहिए। यह वास्तव में IO को मॉडल करने के लिए मठों का उपयोग करने का एक बड़ा हिस्सा है।

IO a प्रकार की अभिव्यक्ति के बारे में सोचा जा सकता है जो एक ऐसी क्रिया का प्रतिनिधित्व करता है जो वास्तविक दुनिया के साथ बातचीत कर सकता है और यदि निष्पादित किया जाता है, तो परिणाम कुछ प्रकार a । उदाहरण के लिए, फ़ंक्शन getLine :: IO String प्रस्ताव से getLine :: IO String मतलब यह नहीं है कि getLine नीचे कुछ विशिष्ट स्ट्रिंग है जिसे मैं निकाल सकता हूं - इसका मतलब है कि getLine मानक इनपुट से लाइन प्राप्त करने की क्रिया का प्रतिनिधित्व करता है।

आश्चर्य की बात नहीं, main :: IO () चूंकि हास्केल कार्यक्रम एक गणना / कार्रवाई का प्रतिनिधित्व करता है जो वास्तविक दुनिया के साथ बातचीत करता है।

चीजें जो आप टाइप IO a भावों को कर सकते हैं क्योंकि IO एक सन्यासी है:

  • पहली क्रिया को निष्पादित करने वाली नई क्रिया का उपयोग करने के लिए (>>) दो क्रियाओं को अनुक्रमित करें, जो भी उत्पादन किया गया है, और फिर दूसरी क्रिया को निष्पादित करता है।

      -- print the lines "Hello" then "World" to stdout
      putStrLn "Hello" >> putStrLn "World"
    
  • कभी-कभी आप उस मूल्य को नहीं छोड़ना चाहते हैं जो पहली कार्रवाई में उत्पन्न हुआ था - आप वास्तव में इसे एक दूसरी कार्रवाई में खिलाया जाना पसंद करेंगे। उसके लिए हमारे पास >>=IO , यह टाइप (>>=) :: IO a -> (a -> IO b) -> IO b

     -- get a line from stdin and print it back out
     getLine >>= putStrLn
    
  • एक सामान्य मूल्य लें और इसे एक ऐसी क्रिया में परिवर्तित करें, जो आपके द्वारा दिए गए मूल्य को तुरंत वापस कर देती है। यह फ़ंक्शन कम स्पष्ट रूप से उपयोगी है जब तक आप नोटेशन का उपयोग do शुरू नहीं करते do

     -- make an action that just returns 5
     return 5
    

यहाँ IO मठ पर हास्केल विकी से अधिक।

सूची में मोनाड

सूचियों में एक सनक होती है। उनके पास इस के बराबर एक मौन तात्कालिकता है:

instance Monad [] where 
  return x = [x]
  xs >>= f = concat (map f xs)               

हम अपनी गणनाओं में गैर-नियतत्ववाद का अनुकरण करने के लिए उनका उपयोग कर सकते हैं। हम उपयोग करते हैं xs >>= f , समारोह f :: a -> [b] सूची पर मैप किया गया है xs , में से प्रत्येक आवेदन के परिणामों की सूची की एक सूची प्राप्त करने के f के प्रत्येक तत्व से अधिक xs , और के सभी सूचियों परिणाम तब सभी परिणामों की एक सूची में सम्‍मिलित किए जाते हैं। एक उदाहरण के रूप में, हम दो गैर-नियतात्मक संख्याओं का योग करते हैं, जो संकेतन का उपयोग करते हैं, दो सूचियों से पूर्णांकों के सभी युग्मों की सूची द्वारा प्रतिनिधित्व की जाने वाली राशि, प्रत्येक सूची एक गैर-निर्धारक संख्या के सभी संभावित मूल्यों का प्रतिनिधित्व करती है:

sumnd xs ys = do
  x <- xs
  y <- ys
  return (x + y)

या समतुल्य का उपयोग कर liftM2 में Control.Monad :

sumnd = liftM2 (+)

हमने प्राप्त किया:

> sumnd [1,2,3] [0,10]
[1,11,2,12,3,13]

मोनाद को उपप्रधान के रूप में

GHC 7.10 के रूप में, Applicative की एक सुपर क्लास है Monad (यानी, हर प्रकार के जो एक है Monad भी एक होना चाहिए Applicative )। सभी के तरीकों Applicative ( pure , <*> ) के तरीके के मामले में लागू किया जा सकता Monad ( return , >>= )।

यह स्पष्ट है कि pure और return समान उद्देश्यों की सेवा करते हैं, इसलिए pure = return<*> की परिभाषा बहुत अपेक्षाकृत स्पष्ट है:

mf <*> mx = do { f <- mf; x <- mx; return (f x) }                 
       -- = mf >>= (\f -> mx >>= (\x -> return (f x)))
       -- = [r   | f <- mf, x <- mx, r <- return (f x)]   -- with MonadComprehensions
       -- = [f x | f <- mf, x <- mx]                   

यह कार्य मानक पुस्तकालयों में ap रूप में परिभाषित किया गया है।

इस प्रकार यदि आप पहले से ही एक प्रकार के लिए Monad का एक उदाहरण परिभाषित कर चुके हैं, तो आप प्रभावी रूप से इसके लिए "मुफ्त में" के लिए Applicative का एक उदाहरण प्राप्त कर सकते हैं

instance Applicative < type > where
    pure  = return
    (<*>) = ap

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

एक सामान्य गणना से मान निकालने का कोई सामान्य तरीका नहीं है

आप कार्यों में मूल्यों को लपेट सकते हैं और एक संगणना के परिणाम को दूसरे में डाल सकते हैं:

return :: Monad m => a -> m a
(>>=)  :: Monad m => m a -> (a -> m b) -> m b

हालाँकि, एक मोनाद की परिभाषा मोनाद के प्रकार के अस्तित्व की गारंटी नहीं देती है Monad m => ma -> a

इसका मतलब है कि सामान्य तौर पर, एक संगणना से मूल्य निकालने का कोई तरीका नहीं है (यानी "इसे अनचेक करें")। यह कई उदाहरणों के लिए मामला है:

extract :: Maybe a -> a
extract (Just x) = x          -- Sure, this works, but...
extract Nothing  = undefined  -- We can’t extract a value from failure.

विशेष रूप से, कोई कार्य नहीं है IO a -> a , जो अक्सर शुरुआती को भ्रमित करता है; इस उदाहरण को देखें।

कर-अंकन

do -notation मोनाड्स के लिए सिंटैक्टिक शुगर है। ये नियम हैं:

do x <- mx                               do x <- mx
   y <- my       is equivalent to           do y <- my
   ...                                         ...
do let a = b                             let a = b in
   ...           is equivalent to          do ...
do m                                     m >> (
   e             is equivalent to          e)
do x <- m                                m >>= (\x ->
   e             is equivalent to          e)
do m             is equivalent to        m

उदाहरण के लिए, ये परिभाषाएँ समकक्ष हैं:

example :: IO Integer
example =
  putStrLn "What's your name?" >> (
    getLine >>= (\name ->
      putStrLn ("Hello, " ++ name ++ ".") >> (
        putStrLn "What should we return?" >> (
          getLine >>= (\line ->
            let n = (read line :: Integer) in
              return (n + n))))))

example :: IO Integer
example = do
  putStrLn "What's your name?"
  name <- getLine
  putStrLn ("Hello, " ++ name ++ ".")
  putStrLn "What should we return?"
  line <- getLine
  let n = (read line :: Integer)
  return (n + n)

मोनाद की परिभाषा

class Monad m where
    return :: a -> m a
    (>>=) :: m a -> (a -> m b) -> m b

मोनाड्स से निपटने के लिए सबसे महत्वपूर्ण कार्य बाँध ऑपरेटर है >>= :

(>>=) :: m a -> (a -> m b) -> m b
  • के बारे में सोचो ma "एक साथ एक कार्रवाई के रूप में a परिणाम"।
  • एक b परिणाम के साथ a -> mb रूप में "एक कार्रवाई ( a पैरामीटर के आधार पर) के बारे में सोचो ।"

>>= पहली क्रिया से दूसरे तक परिणाम को पाइप करके दो क्रियाओं को एक साथ करता है।

Monad द्वारा परिभाषित अन्य कार्य है:

return :: a -> m a

इसका नाम दुर्भाग्यपूर्ण है: इस return का अनिवार्य प्रोग्रामिंग भाषाओं में पाए गए return कीवर्ड से कोई लेना-देना नहीं है।

return x इसके परिणाम के रूप में तुच्छ क्रिया उपज x (यह निम्नलिखित अर्थों में तुच्छ है :)

return x >>= f       ≡  f x     --  “left identity” monad law
       x >>= return  ≡  x       -- “right identity” monad law


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow