Haskell ReaderT Env IO Configuration

I have the following template, which I do quite often and would like to eliminate. It looks something like this:

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

I would like to reduce this to something like this:

 doSomething = do meta <- find getMetaData 

Unfortunately, I still have not completely wrapped my brain with monad transformers. What is the type of find ? This is (Config -> IO Result) -> Result ? How to write it?

Any tips / explanations that will help me convert monad transformers are greatly appreciated.

Thanks!

+6
source share
1 answer

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 .

+11
source

Source: https://habr.com/ru/post/901666/


All Articles