2010-10-31 19 views
7

मैं एक राज्य इकाई भी त्रुटि हैंडलिंग का समर्थन कर सकते लिखने के लिए की जरूरत है। मैं इस उद्देश्य के लिए किसी भी मोनाद का उपयोग करने के बारे में सोच रहा था क्योंकि यह त्रुटि के कारण के बारे में विवरण भी प्रदान कर सकता है। मुझे शायद मोनैड का उपयोग करके एक राज्य मोनैड की परिभाषा मिली, हालांकि मैं शायद इसके बजाय, इसका उपयोग करने के लिए इसे संशोधित करने में असमर्थ हूं। यहां कोड है:मैं एक राज्य मोनैड कैसे लिख सकता हूं जो त्रुटि प्रबंधन को भी करता है?

newtype StateMonad a = StateMonad (State -> Maybe (a, State)) 

instance Monad StateMonad where 
(StateMonad p) >>= k = StateMonad (\s0 -> case p s0 of 
           Just (val, s1) -> let (StateMonad q) = k val in q s1 
           Nothing -> Nothing) 
return a = StateMonad (\s -> Just (a,s)) 

data State = State 
{ log :: String 
, a :: Int} 

उत्तर

6

दो संभावित समाधान हैं। एक है कि कोड आप ऊपर दी गई के सबसे करीब है है:

newtype StateMonad e a = StateMonad (State -> (Either e a, State)) 

instance Monad (StateMonad e) where 
    (StateMonad p) >>= k = 
     StateMonad $ \s0 -> 
      case p s0 of 
       (Right val, s1) -> 
        let (StateMonad q) = k val 
        in q s1 
       (Left e, s1) -> (Left e, s1) 
    return a = StateMonad $ \s -> (Right a, s) 

data State = State 
    { log :: String 
    , a :: Int 
    } 
+0

मैं पहली बार कोड ब्लॉक और दूसरे के बीच अंतर नहीं दिख रहा। क्या आपने गलती से एक ही कोड को दो बार शामिल किया था, या यदि नहीं, तो क्या आप अंतर को स्पष्ट कर सकते हैं? – seh

+0

@seh, अच्छी पकड़, यह –

+3

अपडेट किया गया है यह भी ध्यान दें कि ये दोनों परिचालन रूप से थोड़ा अलग हैं। दूसरा संस्करण पुन: प्रारंभ करने योग्य त्रुटियों की अनुमति देता है, जबकि पहला संस्करण पहली त्रुटि पर समाप्त होता है। यदि आप लॉगिंग मॉडलिंग कर रहे हैं, तो पहले संस्करण को पता चले कि त्रुटि पर लॉग 'खो देता है'। –

4

आप एक इकाई ट्रांसफार्मर की जरूरत है:

newtype StateMonad e a = StateMonad (State -> Either e (a, State)) 

instance Monad (StateMonad e) where 
    (StateMonad p) >>= k = 
     StateMonad $ \s0 -> 
      case p s0 of 
       Right (val, s1) -> 
        let (StateMonad q) = k val 
        in q s1 
       Left e -> Left e 
    return a = StateMonad $ \s -> Right (a, s) 

data State = State 
    { log :: String 
    , a :: Int 
    } 

अन्य रूप राज्य से निपटने के भीतर से निपटने त्रुटि ले जाता है। इस तरह के mtl के रूप में इकाई ट्रांसफार्मर पुस्तकालयों आप एक नया संस्करण बनाने के लिए अलग अलग monads रचना के लिए अनुमति देते हैं। MTL का उपयोग करके आप

type StateMonad e a = StateT State (Either e) a 

जो आप दोनों राज्य और त्रुटि अपने StateMonad भीतर से निपटने का उपयोग करने की अनुमति देगा निर्धारित कर सकते हैं।

2

तुम हमेशा के अंदर (या इसके विपरीत) एक राज्य इकाई के साथ एक ErrorT इकाई ट्रांसफार्मर का उपयोग कर सकते हैं। all about monads का ट्रांसफार्मर खंड पर एक नज़र डालें।

HTH,

+1

अपडेट किया गया लिंक: http://www.haskell.org/haskellwiki/All_About_Monads – sinelaw

9

(बजाय या तो का उपयोग करने का) Control.Monad.Trans.Except से ExceptT उपयोग पर विचार करें।

import Control.Monad.State 
import Control.Monad.Trans.Except 
import Control.Monad.Identity 

data MyState = S 

type MyMonadT e m a = StateT MyState (ExceptT e m) a 

runMyMonadT :: (Monad m) => MyMonadT e m a -> MyState -> m (Either e a) 
runMyMonadT m = runExceptT . evalStateT m 

type MyMonad e a = MyMonadT e Identity a 
runMyMonad m = runIdentity . runMyMonadT m 

आप monads और इकाई ट्रांसफार्मर के साथ सहज नहीं कर रहे हैं तो मुझे लगता है कि पहले करना चाहते हैं! वे एक बड़ी मदद और प्रोग्रामर उत्पादकता प्रदर्शन जीत हैं।

4

मैं किसी नहीं देखा था यहां कागज का उल्लेख Monad Transformers Step by Step by Martin Grabmüller

मैं इसे monads के संयोजन के बारे में सीखने में बहुत सहायक हो पाया।

संबंधित मुद्दे

 संबंधित मुद्दे