Как мне использовать постоянную государственную монаду со Споком?
Я только начинаю с haskell, и у меня возникают проблемы с базовым "эхо" REST сервером.
Спок выглядел как хорошая отправная точка для REST-сервера, и я, хотя и получил основы монады State, но у меня возникают проблемы с пониманием того, как поставить runState
вокруг кода спока.
Вот код, который я получил до сих пор.
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Monoid
import Web.Spock.Safe
import qualified Control.Monad.State as S
storeData :: String -> S.State String String
storeData val = do S.put val
return val
getData :: S.State String String
getData = do val <- S.get
return val
main :: IO ()
main =
runSpock 11350 $ spockT id $
do get "store" $
text "Would be a call to getData"
1 ответ
Хорошо, так вот версия restartableStateT
взломать для вашего примера:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE Rank2Types #-}
module Main where
import Data.Monoid
import Data.String (fromString)
import Web.Spock.Safe
import qualified Control.Monad.State as S
import Data.IORef
storeData :: (Monad m) => String -> S.StateT String m String
storeData val = do S.put val
return val
getData :: (Monad m) => S.StateT String m String
getData = do val <- S.get
return val
newtype RunStateT s m = RunStateT{ runStateT :: forall a. S.StateT s m a -> m a }
restartableStateT :: s -> IO (RunStateT s IO)
restartableStateT s0 = do
r <- newIORef s0
return $ RunStateT $ \act -> do
s <- readIORef r
(x, s') <- S.runStateT act s
atomicModifyIORef' r $ const (s', x)
main :: IO ()
main = do
runner <- restartableStateT "initial state"
runSpock 11350 $ spockT (runStateT runner) $ do
get "store" $ do
cmd <- param "value"
case cmd of
Nothing -> do
old <- S.lift getData
text $ fromString old
Just new -> do
S.lift $ storeData new
text "Stored."
Как и другой ответ, этот создает единый глобальный IORef
хранить "государство". runner
перешел к spockT
затем может запустить любой StateT String IO
вычисление путем получения состояния от этого IORef
запустить вычисление и вернуть полученное состояние обратно в IORef
,
Я хотел бы повторить из другого ответа, что это не обязательно хорошая идея, потому что в ней нет истории параллелизма. Я думаю, что это можно скрыть, например, с помощью STM, но... Я думаю, что вы должны просто использовать базу данных для такого рода вещей.