在Haskell中重新计算运行时的常量

Spa*_*ter 0 haskell haskell-warp

我正在获取此JSON使用它进行一些计算,并希望使用warp返回结果.现在getJSON显然不可变,根本不会改变.如何在每个http请求上重新评估getJSON?什么是最干净的方式?

 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
Run Code Online (Sandbox Code Playgroud)

K. *_*uhr 7

详细说明@Willem Van Onsem的观点......

即使值getJSON是不可变的,该不可变值也不是字节串.这是一个不可变的IO 动作,它返回一个bytestring,但这并不意味着它每次都返回相同的bytestring.该操作是一个不可变的常量,但这并不意味着bytestring也是一个常量.

这与以下方式类似:

getLine :: IO String
getLine = ... some immutable IO action ...
Run Code Online (Sandbox Code Playgroud)

虽然它本身是一个不可变的值(一个不可变的IO动作),但每次执行动作时都可以返回不同的字符串.

例如,下面的自包含的程序将返回两个不同的JSON字节串,onetwo从两个HTTP请求,都通过相同的启动产生的getJSON作用:

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"
Run Code Online (Sandbox Code Playgroud)