This can be done quite mechanically. Start with the source code:
doSomething = do getMeta <- asks getMetaData meta <- liftIO getMeta ...
Using the third law of the monad , we are allowed to move the part that we want to extract into our own do block:
doSomething = do meta <- do getMeta <- asks getMetaData liftIO getMeta ...
Then we can simply extract this sub-expression and give it a name:
findMetaData = do getMeta <- asks getMetaData liftIO getMeta doSomething = do meta <- findMetaData ...
Finally, let me generalize it by replacing the explicit getMetaData reference with the parameter:
find something = do x <- asks something liftIO x doSomething = do meta <- find getMetaData ...
Now we can upload it to GHCi and ask it to infer the type for us:
*Main> :t find find :: (MonadReader rm, MonadIO m) => (r -> IO b) -> mb
If desired, we can clean it up a bit and remove the dummy name x :
find something = ask >>= liftIO . something
To do this, I used the definition of asks and the rules for discoloration for do-notation .
source share