कमजोर संस्करण
हालांकि यह संभव StateT
के लिए एक अनुप्रयोगी ट्रांसफार्मर परिभाषित करने के लिए नहीं है, यह संभव है काम करता है कि एक कमजोर संस्करण परिभाषित करें। s -> m (a, s)
होने के बजाय, जहां राज्य अगले प्रभाव का निर्णय लेता है (इसलिए m
एक मोनड होना चाहिए), हम m (s -> (a, s))
, या समकक्ष m (State s a)
का उपयोग कर सकते हैं।
import Control.Applicative
import Control.Monad
import Control.Monad.State
import Control.Monad.Trans
newtype StateTA s m a = StateTA (m (State s a))
यह StateT
से सख्ती से कमजोर होती है।हर StateTA
StateT
में बनाया जा सकता है (लेकिन इसके विपरीत):
toStateTA :: Applicative m => StateTA s m a -> StateT s m a
toStateTA (StateTA k) = StateT $ \s -> flip runState s <$> k
Functor
और Applicative
परिभाषित अंतर्निहित m
में State
के संचालन उठाने की सिर्फ बात है:
instance (Functor m) => Functor (StateTA s m) where
fmap f (StateTA k) = StateTA $ liftM f <$> k
instance (Applicative m) => Applicative (StateTA s m) where
pure = StateTA . pure . return
(StateTA f) <*> (StateTA k) = StateTA $ ap <$> f <*> k
और हम परिभाषित कर सकते हैं lift
का एक आवेदक संस्करण:
lift :: (Applicative m) => m a -> StateTA s m a
lift = StateTA . fmap return
अपडेट: असल में उपर्युक्त आवश्यक नहीं है, क्योंकि दो आवेदक फंक्शंस की संरचना हमेशा एक आवेदक (डॉक्टरों के विपरीत) होती है। हमारे StateTA
, Compose m (State s)
isomorphic को है, जो स्वत: Applicative
है:
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
इसलिए हम लिख सकता है सिर्फ
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Applicative
import Control.Monad.State
import Data.Functor.Compose
newtype StateTA s m a = StateTA (Compose m (State s) a)
deriving (Functor, Applicative)
दिलचस्प है, वहाँ अन्य ट्रांसफार्मर हैं (जैसे, 'WriterT',' ExceptT'), जिसका ' आवेदक के उदाहरण के लिए अंतर्निहित प्रकार के कन्स्ट्रक्टर को 'मोनाड' होना आवश्यक है। – kirelagin