haskell – 在Web.Scotty中使用StateT

前端之家收集整理的这篇文章主要介绍了haskell – 在Web.Scotty中使用StateT前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试制作一个将数据存储为状态的愚蠢的网络服务器.我正在使用 Web.Scotty. I’ve used ReaderT before with scotty to access config,但遵循相同的方法在这里不起作用.它会根据每个请求重置状态.

我想在程序启动时设置初始状态,然后在程序的整个生命周期中保持相同的状态.

我怎样才能做到这一点? (以下为每个请求创建一个新状态)

  1. {-# LANGUAGE OverloadedStrings #-}
  2. import Web.Scotty.Trans
  3. import Control.Monad.State (StateT,evalStateT,lift)
  4. import qualified Control.Monad.State as S
  5. import Data.Text.Lazy (Text)
  6.  
  7. main :: IO ()
  8. main = do
  9. let runner = flip evalStateT "message"
  10. scottyT 3000 runner runner routes
  11.  
  12. routes :: ScottyT Text (StateT Text IO) ()
  13. routes = do
  14.  
  15. get "/data" $do
  16. val <- lift S.get
  17. text val
  18.  
  19. put "/data/:val" $do
  20. val <- param "val"
  21. lift $S.put val
  22. text val

解决方法

您所看到的行为绝对是预期的行为:
注意 documentation for scottyT中第三个参数的注释:

-> (m Response -> IO Response) — Run monad m into IO,called at each action.

您可以做的是将状态存储在StateT monad外部,以便您可以在每个操作的处理程序中恢复它.我能想到的最天真的方式是这样的:

  1. main :: IO ()
  2. main = do
  3. let s0 = "message"
  4. let transform = flip evalStateT s0
  5. runner <- restartableStateT s0
  6. scottyT 3000 transform runner routes
  7.  
  8. restartableStateT :: s -> IO (StateT s IO a -> IO a)
  9. restartableStateT s0 = do
  10. r <- newIORef s0
  11. return $\act -> do
  12. s <- readioRef r
  13. (x,s') <- runStateT act s
  14. atomicModifyIORef' r $const (s',x)

但这并没有真正解决如果两个请求同时进入会发生什么,它只是“最后一个完成胜利”.

猜你在找的HTML相关文章