2011-11-16 14 views
6

Mam następujący szablon, który wykonuję dość często i chciałbym wyeliminować. Wygląda to mniej więcej tak:Haskell ReaderT Env IO płyta montażowa

type Configured = ReaderT Config 

doSomething :: Configured IO Data 
doSomething = do 
    getMeta <- asks getMetaData 
    meta <- liftIO getMeta 

chciałbym zmniejszyć, że aby coś takiego:

doSomething = do 
    meta <- find getMetaData 

Niestety, jeszcze nie całkowicie owinięty wokół mojego umysłu transformatorów monada jeszcze. Jaki jest typ find? Czy to jest (Config -> IO Result) -> Result? Jak mogę to napisać?

Wszelkie wskazówki/wyjaśnienia, które pomogą mi w konstruowaniu transformatorów Monok są bardzo cenione.

Dzięki!

+3

Nie mam teraz czasu, żeby to wyjaśnić, ale oto coś: typ 'find' to' (Config -> IO Result) -> Skonfigurowany wynik IO "w twoim przykładzie i bardziej ogólnie' Monad m = > (r -> ma) -> ReaderT rma'. Możesz zdefiniować go jako 'find = ask> => lift'. – Miikka

Odpowiedz

11

Można to zrobić w dość mechaniczny sposób. Zacznijmy od oryginalnego kodu:

doSomething = do 
    getMeta <- asks getMetaData 
    meta <- liftIO getMeta 
    ... 

Korzystanie the third monad law, wolno nam przenieść część chcemy wyodrębnić w do-bloku własnych:

doSomething = do 
    meta <- do getMeta <- asks getMetaData 
       liftIO getMeta 
    ... 

Dalej, możemy po prostu wyodrębnić że podwyrażenie i nadać mu nazwę:

findMetaData = do getMeta <- asks getMetaData 
        liftIO getMeta 

doSomething = do 
    meta <- findMetaData 
    ... 

Wreszcie niech go uogólniać zastępując wyraźne odniesienie do getMetaData z parametrem:

find something = do x <- asks something 
        liftIO x 

doSomething = do 
    meta <- find getMetaData 
    ... 

Teraz możemy załadować go w GHCi i poprosić go, aby ustalić typ dla nas:

*Main> :t find 
find :: (MonadReader r m, MonadIO m) => (r -> IO b) -> m b 

Opcjonalnie możemy chcieć je posprzątać trochę i usunięcie manekina wymienić x:

find something = ask >>= liftIO . something 

Aby to zrobić, użyłem the definition of asks i the desugaring rules for do-notation.

+2

I jeszcze jeden krok (jak zauważył Miikka) daje "find = ask> => liftIO". Dzięki! Teraz ma sens. – So8res