2015-12-20 10 views
9

Çoğu monadic fonksiyonlar saf argümanlar alır ve monadik bir değer döndürür. Ama örneğin, aynı zamanda monadic argümanlar gerektiğini birkaç vardır:Serbest (veya daha özgür) monadlarla monadik argümanları alan eylemler nasıl kodlanır?

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) 

Her biri farklı bir problemi getirmek gibi görünüyor ve ben kullanarak nasıl kodlamak tür eylemleri genel bir şekilde bir kavrayışa alamayan ücretsiz monad. finally ve forkIO sorun Her iki

  • monadik bağımsız değişken sonuç daha farklı bir tipte olmasıdır. Ancak ücretsiz için, IO a kodunun, data MyFunctor x = Finally x x x gibi sadece IO a -> IO a -> IO a kodlamasını yapacak şekilde, kodlama türünün tip değişkeni ile değiştirilmeleri gerekir.

    From zero to cooperative threads in 33 lines of Haskell code yazar

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

    uygulamak yumruk Fork next next kullanır ve sonra giriş ve çıkış farklı türleri vardır

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

    uygulamak için kullanır. Ama bunun bir süreçten mi yoksa sadece bu amaç için işe yarayan geçici bir fikirden mi kaynaklandığını anlamıyorum.

    data F b = MZero | MPlus b b 
    

    >>= dağıtmaktadır

    olarak saf bir kodlama ve suggested better implementation daha karmaşıktır:

  • mplus özellikle karmaşıktır. Ve ayrıca ücretsiz bir MonadPluswas removed from free'un yerel bir uygulaması. freer yılında

    o niye MPlusNonDetEff Bool yerine NonDetEff a a olan

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

    ekleyerek uygulanacağı? Ve Free ile çalışmak için bir yolu var, nerede CoYoneda functor kullanarak dışında bir functor olmak için veri türü ihtiyacımız var?

  • forkExec için Nasıl devam edeceğimi bilmiyorum.
+0

O geliyor bana Uygulama, işlevin türüne değil, semantiklerine bağlıdır. “Ama bunun bir süreçten türetilmiş olup olmadığını anlamıyorum.” “Sürecin” burada sadece alanınızı doğru bir şekilde modellemek olduğunu düşünüyorum. Örneğin, "en genel" istisna fonksiyonlarını ('throw', 'catch'?) Kodlamayı denerseniz, 'nihayet' kodlamasının daha açık olacağını düşünüyorum. 'Nihaî' türü '<* '.. ile aynıdır, dolayısıyla teorik olarak bu tür bir fonksiyonun kodlanmasının bir nedeni yoktur (belki de doğrudan değil ..). – user2407038

+0

@ user2407038 Ne demek istediğini anlıyorum. Ancak "tüm arayüzü mekanik olarak kodlayın ve yorumlayıcının uygulama detayları konusunda endişelenmesine izin verin" yaklaşımıyla ilgileniyorum. –

cevap

3

Sadece Freer monad parçası hakkında cevap vereceğim.RollaBool ile birleşik ve ikinci değişken türüdür, MPlus uygulandığında biz

type NonDetComp = Freer NonDetEff 

tanımlayabilir

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

ile şimdi

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

: tanımı hatırlayın Temel olarak bir tuple olan Bool -> NonDetEff b:

Bir örnek olarak 0
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) 

yüzden olmayan deterministik hesaplamaları

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

için MonadPlus örneği tanımlamak ve bunları çalıştırabilirsiniz

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