2013-09-07 7 views
14

मैं वर्तमान में Data.Fresh और Control.Monad.Trans.Fresh पर काम कर रहा हूं, जो कि राहत देता है। ताजा चर उत्पन्न करने के लिए एक इंटरफ़ेस परिभाषित करें, और एक मोनाड ट्रांसफॉर्मर जो इस इंटरफ़ेस को लागू करता है।क्या यह लागू करना संभव है (आवेदक एम) => आवेदक (राज्य टी एस) `?

मैंने शुरू में सोचा था कि के लिए उदाहरण को लागू करना संभव होगा, केवल Applicative m मौजूद है। हालांकि, मैं अटक गया और ऐसा लगता है कि मुझे Monad m की आवश्यकता है। मेरी हास्केल फू पर भरोसा नहीं, मैं तो ट्रांसफार्मर पैकेज में बदल गया है, और मैं क्या Control.Monad.Trans.State.Lazy और .Strict में पाया से आश्चर्यचकित था: बराबर अर्थ विज्ञान के साथ एक उदाहरण बनाना संभव यह है:

instance (Functor m, Monad m) => Applicative (StateT s m) where 
    pure = return 
    (<*>) = ap 
तो यहाँ

मेरे सवाल है निम्नलिखित उदाहरण सिर के साथ?

instance (Applicative m) => Applicative (StateT s m) where 
+0

दिलचस्प है, वहाँ अन्य ट्रांसफार्मर हैं (जैसे, 'WriterT',' ExceptT'), जिसका ' आवेदक के उदाहरण के लिए अंतर्निहित प्रकार के कन्स्ट्रक्टर को 'मोनाड' होना आवश्यक है। – kirelagin

उत्तर

12

पर विचार करें आप दो कार्य है:

f :: s -> m (s, a -> b) 
g :: s -> m (s, a) 

और आप से आप के ऊपर एक s एक समारोह h = StateT f <*> StateF g

h :: s -> m (s, b) 

बनाना चाहते हैं आप f को पारित कर सकते हैं ताकि आप है:

f' :: m (s, a -> b) 
g :: s -> m (s, a) 

f' में से s प्राप्त करने के लिए आपको मोनाड की आवश्यकता है (जो भी आप आवेदक के साथ करेंगे, वह अभी भी m s के रूप में होगा, इसलिए आप g पर मान लागू नहीं कर पाएंगे)।

आप परिभाषाओं के साथ खेल सकते हैं और free monad का उपयोग कर सकते हैं लेकिन राज्य के पतन के लिए आपको join की आवश्यकता है।

+0

मैंने पहले ही ऐसा सोचा था, क्योंकि मुझे लगातार कुछ मीटर (एम ए) 'के साथ सामना करना पड़ा था। –

+1

@Rhymoid: आप 'एक छोड़ते हैं -> b' हिस्सा आप मिलेगा' च ':: मीटर s' और 'जी :: रों -> मीटर b'। इसलिए 'के लिए <*>' 'लागू करने StateT' के एक कार्यान्वयन देना होगा' >> = '' के लिए यह सोचते हैं m' 's' मनमाने ढंग से हो सकता है। –

+0

निश्चित रूप से यह गलत है? इसलिए परिभाषा से यह एक अनुप्रयोगी है StateT, एक इकाई है, और इसलिए मानक पुस्तकालयों में वे केवल राज्य '(<*>) = ap'। लेकिन क्या है कि मतलब है कि आप को लागू करने में सक्षम होना चाहिए (<*>) 'सीधे, केवल का उपयोग कर' (<*>) 'या' भीतरी अनुप्रयोगी से fmap' है '। परेशानी यह है कि मैं नहीं देख सकता कि इसे कैसे किया जाए। –

5

हालांकि, के रूप में पिछले जवाब में बताया गया है, इस उदाहरण सामान्य रूप में परिभाषित नहीं किया जा सकता है, यह ध्यान देने योग्य है कि, जब fApplicative है और sStateT s f भी Applicative है एक Monoid है, क्योंकि यह एक संरचना के रूप में माना जा सकता है अनुप्रयोगी functors की: एक Applicative ट्रांसफार्मर के

StateT s f = Reader s `Compose` f `Compose` Writer s 
+0

वास्तव में किस प्रकार इस अनुप्रयोगी functor आप 'StateT' से संबंधित परिभाषित किया गया है? – kirelagin

4

कमजोर संस्करण

हालांकि यह संभव 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 से सख्ती से कमजोर होती है।हर StateTAStateT में बनाया जा सकता है (लेकिन इसके विपरीत):

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) 
+0

बहुत दिलचस्प है। अपने आवेदन में, राज्य में ही (ताजा मूल्यों की आपूर्ति) जरूरी अगले प्रभाव तय नहीं है, यह सिर्फ कितनी बार दोहराया गया और निकाला जाता है। मेरे कार्यान्वयन में से एक इस समस्या के आसपास हो सकता है, दूसरा अभी तक नहीं; शायद यह जवाब उपयोग का हो सकता है। धन्यवाद! –

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