तुम क्या चाहते StateT s IO (String, Bool)
, जहां StateT
(mtl
पैकेज से) दोनों Control.Monad.State
द्वारा प्रदान की जाती है और Control.Monad.Trans.State
(transformers
पैकेज से) है।
इस सामान्य घटना को एक मोनड ट्रांसफार्मर कहा जाता है, और आप उन्हें Monad Transformers, Step by Step में एक महान परिचय पढ़ सकते हैं।
उन्हें परिभाषित करने के दो दृष्टिकोण हैं। उनमें से एक transformers
पैकेज में पाया गया है जो उन्हें लागू करने के लिए MonadTrans
कक्षा का उपयोग करता है। दूसरा दृष्टिकोण mtl
वर्ग में पाया जाता है और प्रत्येक मोनड के लिए एक अलग प्रकार की कक्षा का उपयोग करता है।
transformers
दृष्टिकोण का लाभ एक ही प्रकार स्तरीय सब कुछ को लागू करने का प्रयोग होता है (here पाया जाता है):
:
class MonadTrans t where
lift :: Monad m => m a -> t m a
lift
दो अच्छा गुण जो MonadTrans
के किसी भी मामले को पूरा करना चाहिए है
(lift .) return = return
(lift .) f >=> (lift .) g = (lift .) (f >=> g)
ये छिपाने में मज़ेदार कानून हैं, जहां (lift .) = fmap
, return = id
और (>=>) = (.)
।
mtl
प्रकार स्तरीय दृष्टिकोण के अपने फायदे भी है, और कुछ बातें केवल सफाई से हो mtl
प्रकार-वर्गों का उपयोग हल कर सकते हैं, हालांकि नुकसान तो प्रत्येक mtl
प्रकार स्तरीय कानूनों आप के स्वयं के सेट है कि याद रखने के लिए जब इसके लिए उदाहरण लागू करें। उदाहरण के लिए, MonadError
प्रकार स्तरीय (here पाया जाता है) के रूप में परिभाषित किया गया है:
class Monad m => MonadError e m | m -> e where
throwError :: e -> m a
catchError :: m a -> (e -> m a) -> m a
इस वर्ग भी ससुराल वालों के साथ आता है:
m `catchError` throwError = m
(throwError e) `catchError` f = f e
(m `catchError` f) `catchError` g = m `catchError` (\e -> f e `catchError` g)
ये भेष में सिर्फ इकाई कानूनों, जहां throwError = return
और कर रहे हैं catchError = (>>=)
(और मोनड कानून छद्म श्रेणी में कानून कानून हैं, जहां return = id
और (>=>) = (.)
)।
अपने विशिष्ट समस्या के लिए, जिस तरह से आप अपने प्रोग्राम लिखने होगा ही होगा:
do
-- get the number of games from the command line (already written)
results <- mapM (\game -> playGame game getStdGen) [1..numberOfGames]
... लेकिन जब आप अपने playGame
समारोह लिखने यह या तो दिखाई देगा:
-- transformers approach :: (Num s) => StateT s IO()
do x <- get
y <- lift $ someIOAction
put $ x + y
-- mtl approach :: (Num s, MonadState s m, MonadIO m) => m()
do x <- get
y <- liftIO $ someIOAction
put $ x + y
जब आप एक से अधिक मोनैड ट्रांसफॉर्मर को ढेर करना शुरू करते हैं तो उन दृष्टिकोणों के बीच और अंतर होते हैं, लेकिन मुझे लगता है कि यह अभी के लिए एक अच्छी शुरुआत है।
आप [MonadRandom] (http://hackage.haskell.org/package/MonadRandom) पैकेज से 'RandT' का भी आनंद ले सकते हैं। –