响应接收的数据类型在 WAI 中



我想知道,为什么WAI的Aplication类型被设计为Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived。为什么不Request -> (Response -> IO ()) -> IO ()?文档说

一种特殊数据类型,用于指示 WAI 处理程序已收到响应。这是为了避免在应用程序的定义中需要 Rank2Type。

强烈建议只有 WAI 处理程序导入并使用此数据类型的数据构造函数。

这种特殊的数据类型如何帮助避免Rank2Types

Application真的应该是

type Application = Request -> (forall b. (Response -> IO b) -> IO b)
-- a.k.a. Request -> Codensity IO Response
-- newtype Codensity f a = Codensity { runCodensity :: forall b. (a -> f b) -> f b }
-- which is closely related to continuations

也就是说,Application取一个Request,一个函数f,它用一个Response调用f

app :: Application
app req f = f _resp

Application迫使你打电话给f。除了f之外,没有其他函数能够在app内部产生IO b,所以,由于app必须产生IO bapp必须调用fwai取决于调用fapp,它可以用这个Application强制执行它。但是,Application排名较高,这有些不可取。

实际使用的解决方案是:

type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
-- a.k.a. Request -> ContT ResponseReceived IO Response
-- in general, ContT is "bigger" and "weaker" than Codensity
-- but, in exchange, does not require higher ranked types
app :: Application
app req f = f _resp

f仍然是app手头唯一可以产生ResponseReceived的东西,只要app不违反它与wai的契约并导入构造函数。您不能将ResponseReceived替换为().每个人和他们的母亲都有构造函数(()(()可用。我认为甚至不可能没有它。这使得它不适合Application

type Application = Request -> (Response -> IO ()) -> IO ()
app :: Application
app _ _ = return () -- uh oh

最新更新