2014-06-15 4 views
12

मैं इस लिखा है समाप्त इतना है कि मैं एक monadic गुना जल्दी समाप्त कर सकते हैं:एक monadic गुना जल्दी

myfoldM    :: (Monad m) => (a -> b -> m (Maybe a)) -> a -> [b] -> m (Maybe a) 
myfoldM _ a []  = return $ Just a 
myfoldM f a (x:xs) = do ma <- f a x; 
          case ma of 
          Nothing -> return Nothing 
          Just a' -> myfoldM f a' xs 

और अगर वहाँ एक और अधिक सुरुचिपूर्ण इस या कुछ इसी तरह से मौजूद है, तो व्यक्त करने के लिए रास्ता है मैं सोच रहा हूँ एक पुस्तकालय में हूँ। बेशक Maybe को Either के साथ बदलकर एक समान संस्करण है।

import Control.Monad (foldM,Monad,mzero) 
import Control.Monad.Trans.Maybe (MaybeT(..)) 
import Control.Monad.Trans.Class (lift) 

myfoldM' :: (Monad m) => (a -> b -> MaybeT m a) -> a -> [b] -> m (Maybe a) 
myfoldM' f = (runMaybeT .) . foldM f 

go :: Int -> Int -> MaybeT IO Int 
go s i = do 
    lift $ putStrLn $ "i = " ++ show i 
    if i <= 4 then return (s+i) else mzero 

test n = do 
    myfoldM' go 0 [1..n] >>= print  

-- test 3 => Just 6 
-- test 5 => Nothing 
+3

अपना खुद का गुना न लिखें, अपना फ़ंक्शन लपेटें ताकि यह मानक गुना के साथ काम करे। –

+1

अनिवार्य रूप से यह सवाल है कि मैं पूछ रहा हूं - क्या आप मुझे ऐसा करने का उदाहरण दे सकते हैं? – ErikR

उत्तर

12

यह सिर्फ एक मानक monadic foldM जल्दी बाहर निकलने के साथ बढ़ाया है:

अद्यतन ... यहाँ एक पूर्ण समाधान पेट्र Pudlák के जवाब पर आधारित है। यह सिर्फ MaybeT में आंतरिक गणना लपेटकर द्वारा किया जा सकता है:

import Control.Monad 
import Control.Monad.Trans.Error 
import Control.Monad.Trans.Maybe 

myfoldM :: (Monad m) => (a -> b -> m (Maybe a)) -> a -> [b] -> m (Maybe a) 
myfoldM f = (runMaybeT .) . foldM ((MaybeT .) . f) 

लेकिन मैं कहेंगे यह अधिक सुविधाजनक है के लिए तह समारोह सीधे MaybeT का उपयोग कर दिए जाने की, क्योंकि तब यह आसानी से mzero द्वारा गणना समाप्त कर सकते हैं,

myfoldM' :: (Monad m) => (a -> b -> MaybeT m a) -> a -> [b] -> m (Maybe a) 
myfoldM' f = (runMaybeT .) . foldM f 

Either के लिए यह एक ही है:: बजाय Maybe मूल्यों से छेड़छाड़ की है, और इस तरह के एक मामले में यह लगभग इसके लिए एक अलग समारोह लेखन के लायक नहीं है

myfoldM'' :: (Monad m, Error e) 
      => (a -> b -> ErrorT e m a) -> a -> [b] -> m (Either e a) 
myfoldM'' f = (runErrorT .) . foldM f 
+3

पॉइंटफुल फॉर्म में पढ़ने के लिए थोड़ा आसान हो सकता है: 'myfoldM f e l = runMaybeT (foldM (\ i o -> (हो सकता है) (f i o)) e l)' ' –

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