किन स्थितियों में liftIO
उपयोग किया जाना चाहिए? जब मैं उपयोग कर रहा होता हूं ErrorT String IO
, तो lift
फ़ंक्शन IO क्रियाओं को ऊपर उठाने का काम करता है ErrorT
, इसलिए liftIO
यह बहुत ही अच्छा लगता है।
जवाबों:
lift
हमेशा "पिछली" परत से लिफ्ट करता है। यदि आपको दूसरी परत से उठाने की आवश्यकता है, तो आपको आवश्यकता होगीlift . lift
।
दूसरी ओर, liftIO
हमेशा IO परत से लिफ्ट करता है (जो, जब मौजूद होता है, हमेशा स्टैक के तल पर होता है)। इसलिए, यदि आपके पास भिक्षुओं की 2 से अधिक परतें हैं, तो आप सराहना करेंगे liftIO
।
निम्नलिखित लंबों में तर्क के प्रकार की तुलना करें:
type T = ReaderT Int (WriterT String IO) Bool
> :t \x -> (lift x :: T)
\x -> (lift x :: T) :: WriterT String IO Bool -> T
> :t \x -> (liftIO x :: T)
\x -> (liftIO x :: T) :: IO Bool -> T
लिफ़्टियो, आईओ मोनाद का एक शॉर्टकट है, आप जिस भी मोनाड में हैं, मूल रूप से, लिफ़्टियो एक परिवर्तनीय संख्या में लिफ्टों का उपयोग करने के लिए बराबर है। सबसे पहले यह बेमानी लग सकता है, लेकिन लिफ़्टियो का उपयोग करने का एक बड़ा फायदा है: यह आपके आईओ कोड को वास्तविक मोनाड निर्माण के प्रति उदासीन बना देता है, ताकि आप उसी कोड का पुन: उपयोग कर सकें चाहे आपके अंतिम मोनाड की परत कितनी बनी हो (यह काफी महत्वपूर्ण है जब एक मोनड ट्रांसफार्मर लिख रहा हो)।
ओह्टर पर, लिफ्टियो मुफ्त में नहीं आ रहा है, जैसा कि लिफ्ट करता है: आपके द्वारा उपयोग किए जाने वाले मोनाड ट्रांसफार्मर इसके लिए समर्थन होना चाहिए, जैसे कि आप जिस मोनाड में होना चाहिए वह मोनाडिओ वर्ग का एक उदाहरण है, लेकिन आजकल अधिकांश मोनाड्स करते हैं (और निश्चित रूप से, टाइप-चेकर यह आपके लिए संकलन समय पर जाँच करेगा: यह हास्क की ताकत है)।
पिछले उत्तर सभी अंतर को अच्छी तरह से समझाते हैं। मैं सिर्फ आंतरिक कामकाज पर कुछ प्रकाश डालना चाहता था ताकि यह समझना आसान हो सके कि liftIO
कुछ जादुई नहीं है (मेरे जैसे नौसिखिए हास्केलर्स के लिए)।
liftIO :: IO a -> m a
एक बुद्धिमान उपकरण है बस पर निर्माण
lift :: (Control.Monad.Trans.Class.MonadTrans t, Monad m) => m a -> t m a
और सबसे ज्यादा इस्तेमाल तब किया जाता है जब नीचे का मोनाड होता है IO
। के लिए IO
इकाई यह की परिभाषा काफी सरल है।
class (Monad m) => MonadIO m where
liftIO :: IO a -> m a
instance MonadIO IO where
liftIO = id
यही कारण है कि साधारण ... liftIO
बस वास्तव में id
के लिए IO
इकाई और मूल रूप से IO
केवल एक ही है कि प्रकार वर्ग की परिभाषा के भीतर आता है।
बात यह है कि जब हमारे पास एक मोनाड प्रकार होता है, जो कि मोनाड ट्रांसफॉर्मर की कई परतों से बना होता है IO
, तो हम बेहतर रूप MonadIO
से उन मोनाड ट्रांसफॉर्मर परतों में से प्रत्येक के लिए एक उदाहरण है। उदाहरण के लिए MonadIO
के कहने MaybeT m
की आवश्यकता m
का होना MonadIO
और साथ ही typeclass।
एक MonadIO
उदाहरण लिखना मूलतः एक बहुत सरल कार्य है। इसके लिए MaybeT m
इसे परिभाषित किया गया है
instance (MonadIO m) => MonadIO (MaybeT m) where
liftIO = lift . liftIO
या के लिए StateT s m
instance (MonadIO m) => MonadIO (StateT s m) where
liftIO = lift . liftIO
वे सभी एक जैसे हैं। सोचिए जब आपके पास 4 लेयर का ट्रांसफार्मर स्टैक है तो आपको या तो करना होगा lift . lift . lift . lift $ myIOAction
या बस liftIO myIOAction
। यदि आप इसके बारे में सोचते हैं, तो हर lift . liftIO
एक स्टैक में आपको एक परत नीचे ले जाएगा , जब तक कि वह नीचे सभी तरह से खोदता नहीं है IO
जहां liftIO
पर परिभाषित किया गया है id
और lift
ऊपर दिए गए रचित s जैसे कोड के साथ अंतिम रूप देता है।
तो यह मूल रूप से ट्रांसफार्मर स्टैक कॉन्फ़िगरेशन की परवाह किए बिना है, बशर्ते कि सभी अंडरलेइंग परतें सदस्य हैं MonadIO
और MonadTrans
एक ही liftIO
ठीक है।
liftIO
IO परत को उठाने के लिए उपयोग करूंगा भले हीlift
पर्याप्त हो, क्योंकि तब मैं मोनाड स्टैक को बदल सकता हूं और कोड अभी भी काम करता है।