2012-02-09 10 views
6

मैं वर्तमान में एक प्रोजेक्ट लिख रहा हूं जहां मैं ListT मोनैड ट्रांसफॉर्मर का भारी उपयोग करता हूं। सादे सूचियों का उपयोग करते समय, नोडेटर्मिनिज्म को लागू करना बहुत आसान है। हालांकि एक बार मुझे अपना कोड ListT में परिवर्तित करना पड़ा, तो यह अधिक जटिल मिला।सूचियों और सूची टी मोनैड ट्रांसफार्मर के बीच कैसे साफ रूप से परिवर्तित करें?

एक साधारण उदाहरण के रूप में: [a] वास्तव में दो कार्यों रचना की आवश्यकता है ListT a करने से परिवर्तित:

conv :: (Monad m) => [a] -> ListT m a 
conv = ListT . return 

हालांकि यह आसान है, मैं इसे पहले से ही वहाँ नहीं है हैरान हूं।

सवाल:

  • वहाँ कुछ बेहतर तरीका nondeterminism जहां एक इकाई ट्रांसफार्मर की जरूरत है संभाल करने के लिए है?
  • क्या सूचियों और ListT के बीच स्पष्ट रूप से आगे और पीछे परिवर्तित करने के लिए कोई तकनीक/पुस्तकालय हैं?

सटीक कारण काफी जटिल हैं, इसलिए मैं नहीं है वास्तव में उस पर बहुत अधिक विस्तृत करना चाहते हैं।

उत्तर

6

मुझे नहीं लगता कि इसके लिए कोई पुस्तकालय हैं; conv एक अविश्वसनीय रूप से सरल कार्य है, आखिरकार, और दूसरी तरफ बस runListT है।

convliftMaybe अक्सर वांछित जब MaybeT का उपयोग कर के समान है:

liftMaybe :: (Monad m) => Maybe a -> MaybeT m a 
liftMaybe = MaybeT . return 

मैं इसे liftList की तर्ज पर कुछ नामकरण की सिफारिश करेंगे।

जहाँ तक nondeterminism के लिए एक बेहतर इकाई ट्रांसफार्मर चला जाता है के रूप में, मैं, logict पैकेज पर देखने की अनुशंसा ओलेग के LogicT ट्रांसफार्मर, जो some helpful operations साथ एक निरंतरता के आधार पर बैक ट्रैकिंग तर्क इकाई है पर आधारित है। बोनस के रूप में, []MonadLogic का एक उदाहरण है, ये ऑपरेशन सूचियों पर भी काम करते हैं।


दिलचस्प बात यह है कि हम एक समारोह है कि conv और liftMaybe के पैटर्न generalises परिभाषित कर सकते हैं:

import Data.Foldable (Foldable) 
import qualified Data.Foldable as F 

choose :: (Foldable t, MonadPlus m) => t a -> m a 
choose = F.foldr (\a b -> return a `mplus` b) mzero 

यह शायद अपने कोड काफी भ्रमित कर देगा, तो मैं इसे का उपयोग की सलाह नहीं देते :)

+0

हां, मैं मानता हूं कि 'conv' एक साधारण कार्य है। मुझे आश्चर्य है कि यह पहले से ही नहीं है। 'ListT' मॉड्यूल में शायद ही कोई उपयोगिताएं हैं जो मुझे महसूस करती हैं जैसे मैं पहिया को फिर से शुरू करता हूं। बस इतना ही। – julkiewicz

0

मैं कुछ महीने बाद इस प्रश्न पर आया क्योंकि मैं इस तरह कुछ सोच रहा था।

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} 

import Control.Monad.Trans.Class 
import Control.Monad.Trans.Maybe 
import Control.Monad.Trans.List 


-- | Minimal implementation: either joinLift or joinT 
class (MonadTrans t, Monad m) => MonadTransJoin t m | m -> t, t -> m where 
    joinLift :: (Monad m', Monad (t m')) => m' (m a) -> t m' a 
    joinLift = joinT . lift 

    joinT :: (Monad m', Monad (t m')) => t m' (m a) -> t m' a 
    joinT = (>>= (joinLift . return)) 


instance MonadTransJoin MaybeT Maybe where 
    joinLift = MaybeT 
    joinT = (>>= maybe mzero return) 

instance MonadTransJoin ListT [] where 
    joinLift = ListT 
    joinT = (>>= foldr mcons mzero) 
     where mcons x xs = return x `mplus` xs 

अब तक तो अच्छा-और ListT/[] जोड़ी के लिए मेरी joinT विधि लग रहा है यह ehird के choose के साथ कुछ है जैसे: तो मैं निम्नलिखित के साथ आया था।

लेकिन इसके साथ समस्या यह है कि वास्तव में एक मोनैड ट्रांसफॉर्मर और मोनैड के बीच कोई समान इंटरफ़ेस नहीं है जिसका व्यवहार इसके आधार मोनैड तक चलता है। हमारे पास MaybeT :: m (Maybe a) -> MaybeT m a और ListT :: m [a] -> ListT m a है, लेकिन ओटीओएच हमारे पास StateT :: (s -> m (a, s)) -> StateT s m a है। मुझे नहीं पता कि इसके आसपास जाने का कोई तरीका है या नहीं, इसके लिए निश्चित रूप से

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