2013-03-04 21 views
11

Próbuję dekonstruować monadę IResult z attoparsec na kilka kawałków. Oto IResultPartiality Monad Transformator

data IResult t r = Fail t [String] String 
       | Partial (t -> IResult t r) 
       | Done t r 

to czuje się jak to powinno być kombinacją efektów „stronniczość” i niepowodzenie. Jeśli brak jest reprezentowane tylko Either ([String], String) następnie stronniczość może być

data Partiality t a = Now a | Later (t -> Partiality t a) 

instance Monad (Partiality t) where 
    return = pure 
    (Now a) >>= f = f a 
    (Later go) >>= f = Later $ \t -> go t >>= f 

class MonadPartial t m where 
    feed :: t -> m a -> m a 
    final :: m a -> Bool 

instance MonadPartial t (Partiality t) where 
    feed _ (Now a) = Now a 
    feed t (Later go) = go t 
    final (Now _) = True 
    final (Later _) = False 

(który staje się jego imiennik z a paper by Danielsson podczas korzystania Partiality())

mogę użyć Partiality jako monady bazowej, ale jest tam PartialityT monada transformator?

+1

Jaka jest twoja monadowa instancja dla 'Partiality t'? –

+0

Dodano do głównego pytania. –

Odpowiedz

12

Na pewno jest! Twój Partiality monada jest darmowa monada:

import Control.Monad.Free -- from the `free` package 

type Partiality t = Free ((->) t) 

... a odpowiadający PartialityT to darmowa transformator monada:

import Control.Monad.Trans.Free -- also from the `free` package 

type PartialityT t = FreeT ((->) t) 

Oto przykładowy program pokazujący jak można go używać:

import Control.Monad 
import Control.Monad.Trans.Class 
import Control.Monad.Trans.Free 

type PartialityT t = FreeT ((->) t) 

await :: (Monad m) => PartialityT t m t 
await = liftF id 

printer :: (Show a) => PartialityT a IO r 
printer = forever $ do 
    a <- await 
    lift $ print a 

runPartialityT :: (Monad m) => [a] -> PartialityT a m r -> m() 
runPartialityT as p = case as of 
    [] -> return() 
    a:as -> do 
     x <- runFreeT p 
     case x of 
      Pure _ -> return() 
      Free k -> runPartialityT as (k a) 

Budujemy darmowy transformator monad za pomocą polecenia await, aby zażądać nowych wartości i lift wywołaj akcje w monadzie podstawowej. Dostajemy instancje Monad i MonadTrans za darmo, ponieważ darmowy transformator monad jest automatycznie monadowym i monadowym transformatorem dla danego funktora.

Prowadzimy powyższy program tak:

>>> runPartialityT [1..] printer 
1 
2 
3 
... 

Polecam lekturę this post I wrote about free monad transformers. Jednak nowym oficjalnym domem darmowego transformatora monad jest pakiet free.

Ponadto, jeśli szukasz efektywnego parsera przyrostowego, mam zamiar wydać to jako pakiet pipes-parse w ciągu kilku dni. Możesz sprawdzić current draft here.

+2

Och, oczywiście, że jest! Moja wada polegała na tym, że nie mogłem się zorientować, gdzie powinny znajdować się wewnętrzne monadyczne warstwy i zdefiniować je: 'dane PartialityT t m a = PT {runPT :: m (Partiality t a)}' ... co daje mi tylko jedną wewnętrzną warstwę monadyczną! Dziękuję za pchnięcie we właściwym kierunku (i wynikające z tego oczywiste uogólnienie!) –

+1

Nie ma za co! –

Powiązane problemy