【问题标题】:Post and Get a variable using yesod server使用 yesod 服务器发布和获取变量
【发布时间】:2015-07-20 12:08:41
【问题描述】:
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)

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

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

【问题讨论】:

    标签: haskell yesod


    【解决方案1】:

    在 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
    

    【讨论】:

    • 嗨 leftaroundabout,感谢您在这个问题上花费大量时间...我有这个疑问 storeS &lt;- liftIO $ readIORef (reqStore yourYesod)storedReq &lt;- readIORef store。为什么第一种情况使用liftIO函数?
    • 我的错误,liftIO 在这两种情况下实际上都是需要的。为什么需要它:所有这些“可变变量”实际上只是引用;引用本身存在于 Yesod 或本地范围内,但他们指向的实际可变 content 位于凌乱的一般 IO monad 中,Haskellers 通常避免暴露它。 Yesod 的单子可以访问IO,但只能通过显式提升。
    猜你喜欢
    • 1970-01-01
    • 2013-06-03
    • 2020-12-18
    • 2011-11-21
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多