2012-10-02 3 views
1

스냅에서 산성 상태를 사용 하려다가로드 블록을 쳤습니다.스냅, IO 및 산성 상태

여기까지 내가 지금까지 얻은 바가 있습니다.

먼저 내 산 상태 관련 개체 (그것이 ISBN 번호와 더미 책입니다) :

{-# LANGUAGE DeriveDataTypeable   #-} 
{-# LANGUAGE GeneralizedNewtypeDeriving #-} 
{-# LANGUAGE MultiParamTypeClasses  #-} 
{-# LANGUAGE TemplateHaskell   #-} 
{-# LANGUAGE TypeFamilies    #-} 
{-# LANGUAGE OverloadedStrings   #-} 

module Models where 

import Prelude hiding ((.), id) 
import Control.Category ((.)) 
import Control.Monad.Reader (asks) 
import Data.ByteString (ByteString) 
import Data.SafeCopy (base, deriveSafeCopy) 
import qualified Data.Text as T 
import Data.Typeable (Typeable) 
import Data.Acid (Update, Query, makeAcidic) 
import Control.Monad.Reader (ask) 
import Control.Applicative ((<$>)) 
import Data.Data (Data) 

data Book = Book { isbn :: String } 
    deriving (Eq, Ord, Read, Data, Show, Typeable) 

$(deriveSafeCopy 0 'base ''Book) 

-- Retrieve the book's isbn 
queryIsbn :: Query Book String 
queryIsbn = isbn <$> ask 

$(makeAcidic ''Book ['queryIsbn]) 

그리고 스냅과 통합에서 다음 내 실제 시도.

{-# LANGUAGE TemplateHaskell #-} 
{-# LANGUAGE OverloadedStrings #-} 
module Application where 

import   Control.Monad.Trans.Class (lift) 
import   Data.Text.Encoding (decodeUtf8) 
import   Text.XmlHtml (Node(TextNode),Node (Element), 
       getAttribute, setAttribute, nodeText) 
import   Data.ByteString (ByteString) 
import   Data.Maybe 
import   Snap.Core 
import   Snap.Snaplet 
import   Snap.Snaplet.Heist (Heist, HasHeist(heistLens), heistInit, 
         addSplices, liftHeist, render) 
import   Snap.Util.FileServe 
import   Text.Templating.Heist (HeistT, Template, getParamNode) 
import   Data.Lens.Template 

import Models 
import Data.Acid.Advanced (query') 
import Data.Acid (AcidState, openLocalState, closeAcidState, IsAcidic, query) 
import Data.Text (pack) 
import Control.Monad.IO.Class (liftIO, MonadIO) 
import Snap (snapletValue) 
import Data.Lens.Common (getL, (^$), (^.), Lens) 
import Control.Monad.Reader (ask, asks) 
import Control.Applicative ((<$>)) 
import Data.Typeable (typeOf) 


import Prelude hiding ((.), id) 
import Control.Category ((.), id) 

------------------------------------------------------------------------------ 
type AppHandler = Handler App App 

-------------- 
-- Acid 
--------------- 
-- Used for holding data for the snapplet 
data Acid st = Acid { _state :: AcidState st } 

-- Initializer function for the snapplet 
seedBook = Book "9213-23123-2311" 

acidInit :: SnapletInit b (Acid Book) 
acidInit = makeSnaplet "storage" "Snaplet providing storage functionality" Nothing initializer 

--The 'm' is the type variable of the MonadSnaplet type class. 'b' is the base state, and 'v' is the state of the current "view" snaplet (or simply, current state). 
initializer :: Initializer b v (Acid Book) 
initializer = do 
     st <- liftIO (openLocalState seedBook) 

     --onUnload (closeAcidState st) 
     return $ Acid st 

----------------------- 
-- Snap Global State 
-------------------- 

data App = App 
    { _heist :: Snaplet (Heist App), 
     _acid :: Snaplet (Acid Book) 
    } 

makeLens ''App 
---------------------------------------------------------------------------------- 

instance HasHeist App where 
    heistLens = subSnaplet heist 

----------------------------------------------- 
-- | Initialize app 
----------------------------------------------- 
appInit :: SnapletInit App App 
appInit = makeSnaplet "app" "Website" Nothing $ do 
    h <- nestSnaplet "" heist $ heistInit "templates" 
    a <- nestSnaplet "isbn" acid (acidInit) 
    addRoutes routes --see below 
    addSplices [ ("menuEntry", liftHeist menuEntrySplice) ] 
    return $ App h a 


------------------------------------------------ 
-- | The application's routes. 
------------------------------------------------ 
routes :: [(ByteString, Handler App App())] 
routes = [ ("/books", handleBooks) 
     , ("/contact", render "contact") 
     , ("/isbn",  liftIO doQuery >>= writeBS) 
     , ("",   serveDirectory "static") 
     ] 

-- Is this Function signature possible? Or must it run inside Snap or other monad? 
doQuery :: IO ByteString 
doQuery = do -- ??????????? 
     --somehow retrieve acid store from snaplet 
     --run queryIsbn on it 
     --return isbn string 
     return "BLAH" 


handleBooks :: Handler App App() 
handleBooks = render "books" 

내가 놓친 거지 무엇에 어떤 도움을 크게 감상 할 수있다 : 당신이 볼 수 있듯이, 나는 문자열 ISBN을 반환해야 문제 기능 __ doQuery__ 정의를 갖는입니다. 명확하지 않은 것이 있으면 알려 주시면 질문을 업데이트하겠습니다.

답변

0

난 당신이 사용하고있는 패키지에 대한 아무 생각이 없지만 문제가 openLocalStateIO 행동이라고 단순히처럼 보이지만 당신의 유형 서명이 Initializer 행동으로 그것을 필요로한다.

고정은 거기에 liftIO에 대한 전화를 채우는 것처럼 간단 할 수도 있습니다. 나는 정말로 모르겠지만 ... 나는이 모듈들 각각이 어떤 모듈인지에 관해 모른다.

+0

안녕하세요. 도움에 감사드립니다. 모든 수입을 질문에 추가했습니다. 도움이되는지 알려주세요. 나는 그 동안'liftIO'를 시도 할 것입니다. – drozzy

1

MathematicalOrchid가 정확합니다. 문제에 대한 가장 간단한 대답은 openLocalState 호출에서 liftIO를 사용하는 것입니다.

넓은 시야에서 여기에서 수행중인 작업은 이미 snaplet-acid-state 패키지로 완료되었으므로 사용하는 것이 좋습니다. 저장소에는 사용법을 보여주는 example application도 포함되어 있습니다.

+0

안녕하세요, 추천 해줘서 고마워. 저는 사실 snaplet-acid-state 스냅 릿을 따르고 있습니다 - 단지 산성 상태 만 사용하여 그것을 쓰지 않고 덮어 쓰고있는 것을 이해하고 싶습니다. 또한, 이전의 산성 패키지 인 :-( – drozzy

+0

snaplet-acid-state [liftIO 사용] (https://github.com/mightybyte/snaplet-acid-state/blob/master/src/Snap/Snaplet/) AcidState.hs # L79) 또한 최신 버전의 산 상태를 허용하는 새 버전을 hackage에 업로드했습니다. – mightybyte

+0

감사합니다. 초기화 기능을 알아 냈습니다! 수정 된 코드를 살펴볼 수 있습니까? 특히, (doQuery 함수에서) 산성 상태 객체를 가져 오는 코드가 어떻게 작동하는지 확신 할 수 없습니다. 클래스를 사용하여 수행하지만 클래스없이 이해하려고합니다. – drozzy