0

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...

fyusuf-a
  • 255
  • 1
  • 9
  • It isn't clear what you mean by "is not possible to get it from the parameters". In what sense it is not possible? Also, why reading a value from e.g. an `IORef` is more problematic than reading one from a file? – n. m. could be an AI Feb 18 '22 at 10:16
  • For the first question, because there is only a `Request` parameter to the `managerModifyRequest` function. For the second one, because I can use the filename to get the configuration value. – fyusuf-a Feb 18 '22 at 11:29
  • Your function that reads from a file returns `IO Something`. Your function that reads from an IORef or `MVar` also returns `IO Something`. It isn't clear why one is more problematic than the other. Can you show some code that works, even inefficiently, with values stored in a file? What exactly stops you from modifying this code to use an IORef instead? – n. m. could be an AI Feb 18 '22 at 11:36
  • Reading each time from a file is costly. @chi showed a working example. I did not realize I could use `>>=` to use a pure function with a custom IO value. – fyusuf-a Feb 18 '22 at 11:43
  • I was wondering what doesn't let you come up with this exact kind of example. There isn't anything particularly custom about any IO value. You use >>= (or do notation) when reading from a file or reading from an IORef in exactly the same way. – n. m. could be an AI Feb 18 '22 at 11:54

1 Answers1

2

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
chi
  • 111,837
  • 3
  • 133
  • 218