Haskell ReaderT Env IO样板

时间:2011-11-16 21:58:56

标签: haskell monads monad-transformers

我有以下样板,我经常做,并想消除。它看起来像这样:

type Configured = ReaderT Config

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

我想把它减少到这样:

doSomething = do
    meta <- find getMetaData

不幸的是,我还没有完全理解monad变形金刚。 find的类型是什么?是(Config -> IO Result) -> Result吗?我该怎么写呢?

非常感谢任何帮助我修改monad变形金刚的提示/解释。

谢谢!

1 个答案:

答案 0 :(得分:11)

这可以以相当机械的方式完成。让我们从您的原始代码开始:

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

使用the third monad law,我们可以将我们想要提取的部分移动到自己的do-block中:

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 asksthe desugaring rules for do-notation