2011-11-16 2 views
6

У меня есть следующий шаблон, который я делаю довольно часто и хотел бы устранить. Это выглядит примерно так:Haskell ReaderT Env Конфигурация IO

type Configured = ReaderT Config 

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

я хотел бы уменьшить, что-то вроде этого:

doSomething = do 
    meta <- find getMetaData 

К сожалению, я не полностью обернутый свой ум вокруг монада трансформаторов пока. Какой тип find? Это (Config -> IO Result) -> Result? Как мне написать?

Любые советы/объяснения, которые помогут мне преобразовать трансформаторы монады, очень ценятся.

Спасибо!

+3

У меня нет времени прямо сейчас, чтобы объяснить это, но вот что-то: тип 'find' is' (Config -> IO Result) -> Configured IO Result' в вашем примере и в более общем плане Monad m = > (r -> ma) -> ReaderT rma'. Вы можете определить его как 'find = asks> => lift'. – Miikka

ответ

11

Это можно сделать довольно механически. Начнем с исходного кода:

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

Использование the third monad law, мы позволили переместить часть, мы хотим, чтобы извлечь в сделай блок своего собственного:

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

Далее, мы можем просто извлечь что подвыражения и дать ему имя:

findMetaData = do getMeta <- asks getMetaData 
        liftIO getMeta 

doSomething = do 
    meta <- findMetaData 
    ... 

Наконец, давайте обобщим его, заменив прямую ссылку на getMetaData с параметром:

find something = do x <- asks something 
        liftIO x 

doSomething = do 
    meta <- find getMetaData 
    ... 

Теперь мы можем загрузить его в GHCi и попросить его, чтобы определить тип для нас:

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

При желании мы могли бы хотеть, чтобы очистить его немного и удалить манекен имя x:

find something = ask >>= liftIO . something 

Для этого я использовал the definition of asks и the desugaring rules for do-notation.

+2

И еще один шаг (как отметил Мийкка) дает вам «find = asks> => liftIO». Благодаря! Теперь имеет смысл. – So8res