2014-12-16 16 views
8

Verileri State depolayan bir aptal web sunucusu yapmaya çalışıyorum. Web.Scotty kullanıyorum. I've used ReaderT before with scotty to access config, ancak aynı yaklaşımı izleyerek burada çalışmaz. Her istekte durumu sıfırlar.WebScotty içinde StateT kullanın.Scotty

Program başladığında başlangıç ​​durumunu ayarlamak istiyorum, daha sonra programın tüm ömrü boyunca aynı durumun sabit kalmasını istiyorum.

Bu işi nasıl yapabilirim? notunu documentation for scottyT üçüncü argüman üzerine açıklama:

{-# LANGUAGE OverloadedStrings #-} 
import Web.Scotty.Trans 
import Control.Monad.State (StateT, evalStateT, lift) 
import qualified Control.Monad.State as S 
import Data.Text.Lazy (Text) 

main :: IO() 
main = do 
    let runner = flip evalStateT "message" 
    scottyT 3000 runner runner routes 

routes :: ScottyT Text (StateT Text IO)() 
routes = do 

    get "/data" $ do 
    val <- lift S.get 
    text val 

    put "/data/:val" $ do 
    val <- param "val" 
    lift $ S.put val 
    text val 
+2

Tamamen işlevsel olmayan dillerde (apache, tomcat, vb.) Yazılmış olan web sunucularında bile, genellikle paylaşılan durumu bellekte saklamıyorsunuz .... Kilitleme, kapatma durumunda durumu saklama endişesi, Veriyi kullanıcılara, vb. ile eşleme. Bu, neden veritabanlarının var olduğunun bir türüdür .... Benim tahminim Scotty'de yapmak istediğiniz şeyi yapamazsınız ve Scotty yazarları bunu uygulamak istemeyecektir (ama bu sadece tahminim). – jamshidh

+0

Bu mantıklı. Bunu yapmak için tek nedeni node.js gelen bazı insanlar haskell öğretmek ve bir veritabanına atmadan önce kolay bir ilk adım gibi görünüyor. Guess not :) –

cevap

6

Gördüğünüz davranış beklenen bir kesinlikle (şu yeni devleti her isteği yaratır)

-> (m Response -> IO Response) - Çalıştır Her eylemde çağrılan numaralı IO numaralı telefona çağrılır. Yapabileceğin Ne

her eylemin işleyicisinde kurtarmayı böylece StateT monad dış durumunu saklamak olduğunu. Aklıma gelen en naif yolu, böyle bir şey olacağını yapmalı:

main :: IO() 
main = do 
    let s0 = "message" 
    let transform = flip evalStateT s0 
    runner <- restartableStateT s0 
    scottyT 3000 transform runner routes 

restartableStateT :: s -> IO (StateT s IO a -> IO a) 
restartableStateT s0 = do 
    r <- newIORef s0 
    return $ \act -> do 
     s <- readIORef r 
     (x, s') <- runStateT act s 
     atomicModifyIORef' r $ const (s', x) 

ama bu gerçekten iki istekleri aynı anda geliyor eğer ne olacağını ele almaz, bu galibiyet bitirmek için sadece "sonuncusu ".

+0

bir örnek var ki dikkat Bu tam senaryo için scotty docs https://github.com/scotty-web/scotty/blob/master/examples/globalstate.hs – fommil