发布并使用yesod服务器获取变量

3 haskell yesod

var express = require('express')
var app = express()
var store = undefined

app.post("/", function(req, res){
  store = req.body
})

app.get("/", function(req, res){
  res.send(store)
} 
app.listen(some_port_num)
Run Code Online (Sandbox Code Playgroud)

这是一个简单的nodejs/express服务器应用程序,它将http请求主体存储在全局变量中,并在get请求中发送相同的变量作为响应.

如何在yesod/haskell中编写此代码.我不知道如何在haskell/yesod中使用全局/模块范围的变量.并且,还有其他方法可以在haskell中的两个函数之间共享变量吗?

lef*_*out 6

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

可以从Handlermonad等的任何地方访问Yesod ,例如

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

在程序开始时,reqStore需要通过类似的方式初始化

main :: IO ()
main = do
   ...
   initReqStore = newIORef emptyRequest
   ...
   warp 3000 $ YourYesod ... initReqStore ...
Run Code Online (Sandbox Code Playgroud)

在这样做之前,考虑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
Run Code Online (Sandbox Code Playgroud)