Home > OS >  Can one store a value indexed by a string in the IO monad?
Can one store a value indexed by a string in the IO monad?

Time:02-18

I want to use custom ManagerSettings to build a custom Network.Wreq.Session. I modify from the defaultManagerSettings both managerRawConnection and managerModifyRequest.

I want managerModifyRequest to use a configuration value known at runtime from a file. As I do a lot of requests, I would rather not make a lot of syscalls to get the configuration value from the file.

I find the type managerModifyRequest :: Request -> IO Request to be problematic. How can I use a configuration value if it is not possible to get it from the parameters?

I thought about IORefs and MVars to store the value in memory, but I should be able to pass said IORef or MVar to the function somehow...

CodePudding user response:

I am not familiar with the library, but I guess you need to write something like this:

-- pseudocode
foo = do
   -- create the IORef here
   r <- newIORef "hello"
   let settings = defaultManagerSettings{
          ...
          managerModifyRequest = \req -> do
             -- use the IORef here
             s <- readIORef r
             putStrLn s
             writeIORef r (s    "!!")
             return req
          }
   use settings

You don't need to pass the IORef as an additional argument to managerModifyRequest , you need to define that Request -> IO Request function in the scope where the IORef is available.


Alternatively, use an helper function with the additional argument, and then partially apply it with the IORef:

-- pseudocode
foo = do
   -- create the IORef here
   r <- newIORef "hello"
   let settings = defaultManagerSettings{
          ...
          managerModifyRequest = myManager r
          }
   use settings

myManager :: IORef String -> Request -> IO Request
myManager r req = do
   -- use the IORef here
   s <- readIORef r
   putStrLn s
   writeIORef r (s    "!!")
   return req
  • Related