So8*_*res 6 monads haskell monad-transformers
我有以下样板,我经常这样做,并希望消除.它看起来像这样:
type Configured = ReaderT Config
doSomething :: Configured IO Data
doSomething = do
getMeta <- asks getMetaData
meta <- liftIO getMeta
Run Code Online (Sandbox Code Playgroud)
我想减少到这样的事情:
doSomething = do
meta <- find getMetaData
Run Code Online (Sandbox Code Playgroud)
不幸的是,我还没有完全关注monad变形金刚.是什么类型的find
?是(Config -> IO Result) -> Result
吗?我怎么写呢?
任何提示/解释,以帮助我grok monad变形金刚非常感谢.
谢谢!
ham*_*mar 11
这可以以相当机械的方式完成.让我们从您的原始代码开始:
doSomething = do
getMeta <- asks getMetaData
meta <- liftIO getMeta
...
Run Code Online (Sandbox Code Playgroud)
使用第三个monad定律,我们可以将我们想要提取的部分移动到它自己的do-block中:
doSomething = do
meta <- do getMeta <- asks getMetaData
liftIO getMeta
...
Run Code Online (Sandbox Code Playgroud)
接下来,我们可以提取该子表达式并为其命名:
findMetaData = do getMeta <- asks getMetaData
liftIO getMeta
doSomething = do
meta <- findMetaData
...
Run Code Online (Sandbox Code Playgroud)
最后,让我们通过用getMetaData
参数替换显式引用来概括它:
find something = do x <- asks something
liftIO x
doSomething = do
meta <- find getMetaData
...
Run Code Online (Sandbox Code Playgroud)
现在,我们可以在GHCi中加载它并要求它为我们推断出类型:
*Main> :t find
find :: (MonadReader r m, MonadIO m) => (r -> IO b) -> m b
Run Code Online (Sandbox Code Playgroud)
或者,我们可能希望将其清理一下并删除虚拟名称x
:
find something = ask >>= liftIO . something
Run Code Online (Sandbox Code Playgroud)
为此,我使用了asks
do-notation 的定义和desugaring规则.