2011-10-18 3 views
5

데이터베이스에 대한 많은 액세스 권한을 가진 Happstack 응용 프로그램을 만들고 싶습니다.Happstack에서 데이터베이스 모나드 스택을 만드는 방법은 무엇입니까?

itemsRequest :: ServerConfig -> ServerPart Response 
itemsRequest cf = dir "items" $ do 
    methodM [GET,HEAD] 
    liftIO $ noticeM (scLogger cf) "sended job list" 

    items <- runDBMonad (scDBConnString cf) $ getItemLists 

    case items of 
    (Right xs) -> ok $ toResponse $ show xs 
    (Left err) -> internalServerError $ toResponse $ show err 

으로 : 나는 바닥 (중간에 로그 라이터와) 상단에 데이터베이스 쓰기와 같은 모나드에서 IO와 모나드 스택은 각 액세스 예에서 명확한 기능을 가지고 일 것이라고 생각 :

getItemList :: MyDBMonad (Error [Item]) 
getItemList = do 
    -- etc... 

하지만 모나드와 모나드 변압기 (나는 그것에 대해 배울 수있는 운동으로이 질문을 참조)의 약간의 지식을 가지고, 내가 어떻게 방법 IO를 해제하는 데이터베이스 모나드의 생성을 시작하는 아무 생각이 없다 happstack에서 데이터베이스 스택, ... 등. 이 경우, 우리는 모든 사람이 얻을하려는 값이 데이터베이스 연결이 -

type MyMonad a = ReaderT DbHandle ServerPart a 

Reader 모나드 변압기가 ask 기능을 사용하여 액세스 할 수있는 단일 값을 만드는이 :

+0

'unsafePerformIO'를 사용하여 IO를 시도했습니다. Happstack은 순수한 조합을 사용하기 때문에 IO를 수행하는 유일한 방법 일 수 있습니다. – Nybble

+0

@Wu Xingbo, liftIO를 사용하여 쉼 스택에서 IO를 수행 할 수는 있지만 다른 모나드 스택으로 전달할 사람을 알지 못합니다. – Zhen

답변

6

당신은 가능성 'ReaderT'를 사용하려면 .

여기에서 DbHandle은 데이터베이스에 연결되어 있습니다.

'ReaderT'는 이미 모든 happstack-server type-classes의 인스턴스이므로 모든 일반 happstack-server 기능이이 모나드에서 작동합니다.

당신은 아마 또한 데이터베이스 연결을 열고 닫습니다 도우미의 일종을 원하는

:

runMyMonad :: String -> MyMonad a -> ServerPart a 
runMyMonad connectionString m = do 
    db <- liftIO $ connect_to_your_db connectionString 
    result <- runReaderT m db 
    liftIO $ close_your_db_connection db 

(여기 '브라켓'와 같은 기능을 사용하는 것이 더 좋을 수도 있지만, 내가 모르는이 서버 파트 모나드와 같은 작업 임)

로깅을 어떻게 수행할지 모르겠습니다. 로그 파일과 어떻게 상호 작용할 계획입니까? 다음

type MyMonad a = ReaderT (DbHandle, LogHandle) ServerPart a 

과 : 같은 뭔가

askDb :: MyMonad DbHandle 
askDb = fst <$> ask 

askLogger :: MyMonad LogHandle 
askLogger = snd <$> ask 

충분히있을 수 있습니다. 그런 다음 해당 프리미티브를 기반으로 높은 수준의 기능을 만들 수 있습니다. 을 LogHandle으로 바꾸려면이를 변경해야합니다.

두 개 이상의 항목을 얻으면 튜플 대신 올바른 레코드 유형을 사용하는 것이 좋습니다.

+2

주요 주제 : 연결 풀링을 위해 http://hackage.haskell.org/package/resource-pool 및 http://hackage.haskell.org/package/pool이 있습니다. 그래도 필요한 것 이상일 수 있습니다. –

+0

수영장 팁 주셔서 감사합니다! – Zhen

6

나 같은 혼란스러운 초보자를 위해 위의 발췌 문장에서 컴파일 된 최소한의 작업 코드가 있습니다.

AppConfig 유형에 물건을 넣고 응답 업체 내에 ask을 넣으십시오.

{-# LANGUAGE OverloadedStrings #-} 
module Main where 

import Happstack.Server 
import Control.Monad.Reader 
import qualified Data.ByteString.Char8 as C 

myApp :: AppMonad Response 
myApp = do 
    -- access app config. look mom, no lift! 
    test <- ask 

    -- try some happstack funs. no lift either. 
    rq <- askRq 
    bs <- lookBS "lol" 

    -- test IO please ignore 
    liftIO . print $ test 
    liftIO . print $ rq 
    liftIO . print $ bs 

    -- bye 
    ok $ toResponse ("Oh, hi!" :: C.ByteString) 

-- Put your stuff here. 
data AppConfig = AppConfig { appSpam :: C.ByteString 
          , appEggs :: [C.ByteString] } deriving (Eq, Show) 
config = AppConfig "THIS. IS. SPAAAAAM!!1" [] 

type AppMonad = ReaderT AppConfig (ServerPartT IO) 

main = simpleHTTP (nullConf {port=8001}) $ runReaderT myApp config {appEggs=["red", "gold", "green"]} 
관련 문제