2015-12-20 6 views
9

अधिकांश monadic कार्यों शुद्ध तर्क लेते हैं और एक monadic मूल्य वापस। लेकिन वहाँ उदाहरण के लिए, कुछ भी जरूरत है कि monadic तर्क हैं:उन कार्यों को एन्कोड कैसे करें जो मोनैडिक तर्कों को मुफ्त (या फ्रीर) मोनैड के साथ लेते हैं?

mplus :: (MonadPlus m) => m a -> m a -> m a 

finally :: IO a -> IO b -> IO a 

forkIO :: m() -> m ThreadId 

-- | From Control.Monad.Parallel 
forkExec :: m a -> m (m a) 

उनमें से प्रत्येक एक अलग समस्या को लाने के लिए लगता है और मैं एक सामान्य तरीके की समझ का उपयोग कर कैसे एनकोड इस तरह के कार्यों नहीं मिल सकता है मुफ्त monads।

  • finally और forkIO समस्या दोनों में monadic तर्क परिणाम की तुलना में एक अलग प्रकार की है। लेकिन मुफ्त के लिए उन्हें एक ही प्रकार के होने की आवश्यकता होगी, IO a को एन्कोडिंग प्रकार के प्रकार चर द्वारा प्रतिस्थापित किया जाता है, जैसे data MyFunctor x = Finally x x x, जो केवल IO a -> IO a -> IO a को एन्कोड करेगा।

    From zero to cooperative threads in 33 lines of Haskell code में लेखक Fork next next का उपयोग करता है को लागू

    cFork :: (Monad m) => Thread m Bool 
    cFork = liftF (Fork False True) 
    

    मुट्ठी और फिर

    fork :: (Monad m) => Thread m a -> Thread m() 
    

    जहां इनपुट और आउटपुट विभिन्न प्रकार लागू करने के लिए इसे इस्तेमाल करता है। लेकिन मुझे समझ में नहीं आता कि यह कुछ प्रक्रिया का उपयोग करके लिया गया था या सिर्फ एक विशेष विचार है जो इस विशेष उद्देश्य के लिए काम करता है।

  • mplus भ्रामक विशेष रूप से है:

    के रूप में एक अनुभवहीन एन्कोडिंग
    data F b = MZero | MPlus b b 
    

    >>= से अधिक वितरित करता है और एक suggested better implementation अधिक जटिल है। और एक मुक्त MonadPluswas removed from free का मूल कार्यान्वयन भी।

    freer में यह

    data NonDetEff a where 
        MZero :: NonDetEff a 
        MPlus :: NonDetEff Bool 
    

    जोड़कर लागू हो जाता है क्यों MPlus बजाय NonDetEff BoolNonDetEff a a है? और क्या Free के साथ इसे काम करने का तरीका है, जहां CoYoneda functor का उपयोग करने के अलावा हमें एक मजेदार होने के लिए डेटा प्रकार की आवश्यकता है?

  • forkExec के लिए मुझे नहीं पता कि कैसे आगे बढ़ना है।
+0

मुझे ऐसा लगता है कि कार्यान्वयन फ़ंक्शन के प्रकार पर नहीं बल्कि इसके अर्थशास्त्र पर निर्भर करता है। "लेकिन मुझे समझ में नहीं आता कि यह कुछ प्रक्रिया का उपयोग कर लिया गया था" मुझे लगता है कि यहां 'प्रक्रिया' बस आपके डोमेन को ठीक से मॉडलिंग कर रही है। उदाहरण के लिए, मुझे लगता है कि 'आखिरकार' का एन्कोडिंग अधिक स्पष्ट होगा यदि आप पहले "सबसे सामान्य" अपवाद कार्यों ('throw',' catch'?) को एन्कोड करने का प्रयास करते हैं। 'आखिरकार' का प्रकार '<*' जैसा ही है .. इसलिए सैद्धांतिक रूप से ऐसा कोई कारण नहीं है कि इस प्रकार का फ़ंक्शन एन्कोड नहीं किया जा सकता है (शायद केवल सीधे नहीं ..)। – user2407038

+0

@ user2407038 मैं समझता हूं कि आपका क्या मतलब है। लेकिन मुझे दृष्टिकोण में रूचि है "यांत्रिक रूप से पूरे इंटरफ़ेस को एन्कोड करें और दुभाषिया को कार्यान्वयन विवरण के बारे में चिंता करने दें"। –

उत्तर

3

मैं केवल Freer मोनड भाग के बारे में उत्तर दूंगा।परिभाषा याद:

data Freer f b where 
    Pure :: b -> Freer f b 
    Roll :: f a -> (a -> Freer f b) -> Freer f b 
अब

data NonDetEff a where 
    MZero :: NonDetEff a 
    MPlus :: NonDetEff Bool 

साथ

हम

type NonDetComp = Freer NonDetEff 

परिभाषित कर सकते हैं RollMPlus लिए आवेदन किया है, aBool के साथ एकीकृत है और दूसरा तर्क के प्रकार है जब Bool -> NonDetEff b जो मूल रूप से एक tuple है:

tuplify :: (Bool -> a) -> (a, a) 
tuplify f = (f True, f False) 

untuplify :: (a, a) -> (Bool -> a) 
untuplify (x, y) True = x 
untuplify (x, y) False = y 

एक उदाहरण के रूप:

ex :: NonDetComp Int 
ex = Roll MPlus $ Pure . untuplify (1, 2) 

तो हम गैर नियतात्मक संगणना

instance MonadPlus NonDetComp where 
    mzero  = Roll MZero Pure 
    a `mplus` b = Roll MPlus $ untuplify (a, b) 

के लिए एक MonadPlus उदाहरण को परिभाषित करने और उन्हें चला सकते हैं

run :: NonDetComp a -> [a] 
run (Pure x)  = [x] 
run (Roll MZero f) = [] 
run (Roll MPlus f) = let (a, b) = tuplify f in run a ++ run b 
संबंधित मुद्दे

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