0

I am fetching this JSON use it for some computations and want to return a result, using warp as well. Now getJSON is obviously not mutable and won't change at all. How can I re-evaluate getJSON on every http request? What is the cleanest way?

 getJSON :: IO B.ByteString
    getJSON = do
                let authHeader = ("Authorization", token)
                request' <- parseRequest jsonURL
                let request = request' { requestHeaders = [authHeader] }
                manager <- newManager tlsManagerSettings
                resp <- httpLbs request manager
                return $ responseBody resp
SparklingWater
  • 358
  • 4
  • 15
  • 1
    `getJSON` itself is not mutable like *any* `IO` object, but if you bind multiple `getJSON`s after each other, you will alter the state. – Willem Van Onsem Feb 16 '18 at 22:50

1 Answers1

7

To elaborate on @Willem Van Onsem's point...

Even though the value of getJSON is immutable, that immutable value is not a bytestring. It's an immutable IO action that returns a bytestring, but that doesn't imply that it returns the same bytestring every time. The action is an immutable constant, but that doesn't mean the bytestring is also a constant.

This is similar to the way that:

getLine :: IO String
getLine = ... some immutable IO action ...

while itself an immutable value (an immutable IO action), can return different strings each time the action is executed.

For example, the following self-contained program will return two different JSON bytestrings, one and two resulting from two HTTP requests, both initiated by the same getJSON action:

import qualified Data.ByteString.Lazy.Char8 as B
import Control.Concurrent (threadDelay)
import Network.HTTP.Client

jsonURL :: String
jsonURL = "http://time.jsontest.com"

getJSON :: IO B.ByteString
getJSON = do
  request <- parseRequest jsonURL
  manager <- newManager defaultManagerSettings
  resp <- httpLbs request manager
  return $ responseBody resp

main = do
  one <- getJSON
  threadDelay (3*10^6)  -- delay three seconds
  two <- getJSON
  putStrLn $ "one was:\n" ++ B.unpack one ++ "\n"
  putStrLn $ "two was:\n" ++ B.unpack two ++ "\n"
K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71