나는 Happstack crashcourse를 읽었습니다. 내 웹 서버는 섹션에 설명 된 거의 정확한 방법을 가지고 있습니다. Passing multiple AcidState handles around transparentlyHappstack에서 비 산성 값을 전달하는 방법은 무엇입니까?
문제 저는 산성이 아니지만 Happstack 응용 프로그램 내에서 액세스하려는 가치가 있습니다. 1) PushManager는 내부적으로 많은 데이터 유형을 사용하기 때문에 나는이 일을 만들 수 없습니다
data Acid = Acid
{ acidCountState :: AcidState CountState
, acidGreetingState :: AcidState GreetingState
, acidPushManager :: AcidState PushManager
}
, 그리고/현실적이지 못하다 : 특히 내가 원하는 무엇
, push-notify-general library에서 "PushManager"를 말하는 것은 $ (deriveSafeCopy ...)를 호출하여 기본 데이터 유형 SafeCopy를 호환 가능하게 만듭니다. 2) PushManager는 단순한 값뿐만 아니라 SafeCopy와 호환되는 기능을 포함합니다.
내가 시도한 다른 것은 AcidState 데이터뿐만 아니라 AcidState 데이터도 포함하지 않는 "Acid"데이터 선언입니다. runApp의 정의를 보면 "Acid"가 Reading에만 사용되므로 State Monad로 다시 작성하면 내 필요를 충족시킬 수 있다고 생각했습니다. 그러나 그렇게 단순하지는 않습니다. 그것은 컴파일
{-# LANGUAGE MultiParamTypeClasses, GeneralizedNewtypeDeriving,
TemplateHaskell, TypeFamilies, DeriveDataTypeable,
FlexibleContexts, ScopedTypeVariables,
NamedFieldPuns, DeriveFunctor, StandaloneDeriving, OverloadedStrings #-}
import Control.Applicative (Applicative, Alternative, (<$>))
import Control.Monad (MonadPlus)
import Control.Monad.State.Strict (MonadState, StateT, get, put, evalStateT)
import Control.Monad.Trans (MonadIO)
import Data.Acid
import Data.Data (Data, Typeable)
import Happstack.Server
newtype Simple a = Simple { unSimple :: a }
deriving (Show)
data CountState = CountState { count :: Integer }
deriving (Eq, Ord, Data, Typeable, Show)
-- This data is equivalent to the one previously called "Acid"
data States = States {
simpleState :: Simple Int
, acidCountState :: AcidState CountState
}
initialStates :: States
initialStates = States { simpleState = Simple 1, acidCountState = undefined }
newtype App a = App { unApp :: ServerPartT (StateT States IO) a }
deriving (Functor, Alternative, Applicative, Monad
, MonadPlus, MonadIO, HasRqData, ServerMonad
, WebMonad Response, FilterMonad Response
, Happstack, MonadState States)
class HasSimple m st where
getSimple :: m (Simple st)
putSimple :: (Simple st) -> m()
instance HasSimple App Int where
getSimple = simpleState <$> get
putSimple input = do
whole <- get
put $ whole {simpleState = input}
simpleQuery :: (Functor m
, HasSimple m a
, MonadIO m
, Show a
) =>
m a
simpleQuery = do
(Simple a) <- getSimple
return a
simpleUpdate :: (Functor m
, HasSimple m a
, MonadIO m
, Show a
) =>
a
-> m()
simpleUpdate a = putSimple (Simple a)
runApp :: States -> App a -> ServerPartT IO a
runApp states (App sp) = do
mapServerPartT (flip evalStateT states) sp
rootDir :: App Response
rootDir = do
intVal <- simpleQuery
let newIntVal :: Int
newIntVal = intVal + 1
simpleUpdate newIntVal
ok $ toResponse $ ("hello number:" ++ (show newIntVal))
main :: IO()
main = do
simpleHTTP nullConf $ runApp initialStates rootDir
하지만 때마다 웹 페이지는 페이지 표시 동일한 수의 요청 : 내 임시 코드입니다. 내 코드를 다시 살펴보면 runApp의 evalStateT가 잘못된 것으로 느껴집니다. 업데이트 된 상태 값을 사용하지 않기 때문입니다.
이제 mapServerPartT 및 ServerPartT를 읽었지만 너무 복잡합니다. 누군가가 제목 줄에 대답 할 수 있다면 감사합니다. "Happstack에서 비 산성 값을 전달하는 방법"
다음 단계는 만드는 것입니다 : 데이터 ACI를의 Aci = {acidCountState :: AcidState CountState , acidGreetingState :: AcidState GreetingState , tvarCountState :: TVAR CountState } 및 확인 TVar 작업을위한 몇 가지 쿼리 함수. 그 후에 나는 그것을 TVar PushManager로 대체 할 수 있습니다. – katsu