在 Haskell 中使用全局常量是微不足道的:你只需在某处写 foo = bla(最好带有签名 foo :: FooType)。 foo 然后可以在你的模块中的任何地方使用(或者甚至在外部,如果你导出它的话)。
全局变量 OTOH 在 Haskell 中实际上是不可能的,因此。在大多数情况下,这是一件好事,因为全局状态往往会导致 很多 错误。通常,当程序员考虑全局变量时,事实证明全局常量就可以了,否则最好将可变状态重写为显式参数。
但有时您确实需要状态变量。特别是在 Yesod 中,有一个地方可以在全球范围内存储它们:Yesod。这就是您的 Web 应用程序作为其“地下室”的数据结构。例如,您可能有
data YourYesod = YourYesod {
...
, reqStore :: IORef RequestBody -- IORef basically means, it's variable
-- in the imperative sense.
...
}
mkYesod "YourYesod" [parseRoutes| ... |]
Yesod 可以从 Handler 等单子中的任何位置访问,例如在
getHomeR :: Handler Html
getHomeR = do
...
yourYesod <- getYesod -- gain "access" to the Yesod
storeS <- liftIO $ readIORef (reqStore yourYesod) -- look up the variable state
...
liftIO $ writeIORef (reqStore yourYesod) newStoreS -- write new state
...
在程序开始时,reqStore 需要初始化,类似
main :: IO ()
main = do
...
initReqStore = newIORef emptyRequest
...
warp 3000 $ YourYesod ... initReqStore ...
在这样做之前,请考虑store 变量是否真的需要是全局变量。 Yesod 几乎是你拥有的最全球化的范围。这也意味着像程序语言中的那些典型错误的危险。如果变量只在一个处理程序中使用,你还不如在本地引入它,比如
do
...
store <- newIORef emptyRequest
appPost "/" $ \req res -> do
liftIO $ writeIORef store $ body req
appGet "/" $ \req res -> do
storedReq <- liftIO $ readIORef store
send res storedReq