2012-10-23 16 views
6

एक अनुप्रयोगी functor रीडर इकाई है कि कुछ इस तरह से करता है से बाहर कर मुझे क्या करना चाहते हैं की एक संयोजन बनाना:एक रीडर और हो सकता है कि इकाई (अनुप्रयोगी functor)

data MyData = Int Int 

get2Sum :: Reader [Int] Int 
get2Sum = do 
    myData <- ask 
    let fst2 = take 2 myData 
    case length fst2 of 
     2 -> return $ sum fst2 
     _ -> return 0 

myDataFromApplicative = MyData <$> get2Sum <*> get2Sum 

main = print $ runReader myDataFromApplicative [1,2] 

हालांकि, कुछ अगर चलाने जैसे

runReader myDataFromApplicative [1] 
इसके बजाय मुझे MyData 0 0

देने की

मैं चाहता हूँ यह मेरे Error

देने के लिए

मैं इसे पूरा करने के लिए अपना खुद का रीडर मोनाड बनाने के साथ खेल रहा था, लेकिन इसे काफी समझ नहीं पाया।

क्या मैं कल्पना कुछ इस तरह (जाहिर है यह सिर्फ एक रूपरेखा

data SuccessReader r a = Interm {runSuccessReader :: r -> SuccessReader a} | Success a | Error 
throwError :: SuccessReader() 


get2Sum :: Reader [Int] Int 
get2Sum = do 
    myData <- ask 
    let fst2 = take 2 myData 
    case length fst2 of 
     2 -> return $ sum fst2 
     _ -> throwError 

myDataFromApplicative = MyData <$> get2Sum <*> get2Sum 

main = do 
    print $ runSuccessReader myDataFromApplicative [1,2] 
    print $ runSuccessReader myDataFromApplicative [1] 

है जो होगा उत्पादन

Success MyData 3 3 
Error 

उत्तर

8

के रूप में इस ठीक है आप अपनी खुद की इकाई लिखने की जरूरत नहीं है समस्या है कि मोनैड ट्रांसफार्मर और मोनैड स्टैक्स हल हो जाते हैं। चूंकि आप Reader और Maybe का संयोजन चाहते हैं, तो आप ReaderT ट्रांसफॉर्मर Maybe मोनैड के साथ उपयोग कर सकते हैं।

get2Sum :: ReaderT [Int] Maybe Int 
get2Sum = do 
    myData <- ask 
    let fst2 = take 2 myData 
    case length fst2 of 
     2 -> return $ sum fst2 
     _ -> lift Nothing 

get2Sum के प्रकार मतलब है कि हम बाहरी इकाई Reader [Int] जो भीतरी इकाई Maybe शामिल है। get2Sum के कार्यान्वयन में, lift का उपयोग आंतरिक मोनैड में परिचालन चलाने के लिए किया जाता है (इस मामले में, बस Nothing के साथ त्रुटि सिग्नलिंग)। अब जब आप चलाने के (ध्यान दें टीrunReaderT में)

main = do 
    print $ runReaderT myDataFromApplicative [1,2] 
    print $ runReaderT myDataFromApplicative [1] 

आप

Just (MyData 3 3) 
Nothing 

आप कस्टम newtype

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

import Control.Applicative 
import Control.Monad.Reader 

data MyData = MyData Int Int deriving Show 

newtype MyMonad a = MyMonad (ReaderT [Int] Maybe a) 
    deriving (Functor, Applicative, Monad, MonadReader [Int]) 

runMyMonad :: MyMonad a -> [Int] -> Maybe a 
runMyMonad (MyMonad m) = runReaderT m 

myError :: MyMonad a 
myError = MyMonad $ lift Nothing 

get2Sum :: MyMonad Int 
get2Sum = do 
    myData <- ask 
    let fst2 = take 2 myData 
    case length fst2 of 
     2 -> return $ sum fst2 
     _ -> myError 

myDataFromApplicative = MyData <$> get2Sum <*> get2Sum 

main = do 
    print $ runMyMonad myDataFromApplicative [1,2] 
    print $ runMyMonad myDataFromApplicative [1] 
अंदर इकाई ढेर छुपा सकते मिल
संबंधित मुद्दे