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

时间:2018-02-16 22:48:56

标签: 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

1 个答案:

答案 0 :(得分:7)

详细阐述@Willem Van Onsem的观点...

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

这类似于:

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

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

例如,以下自包含程序将返回两个不同的JSON字节串,onetwo由两个HTTP请求产生,两个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"