首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >快照、IO和acid状态

快照、IO和acid状态
EN

Stack Overflow用户
提问于 2012-10-02 10:38:13
回答 2查看 964关注 0票数 1

尝试在Snap中使用酸状态,但我遇到了障碍。

这是我到目前为止所得到的。

首先是与酸状态相关的对象(它是一个带有isbn编号的虚拟书):

代码语言:javascript
复制
{-# 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])

然后是我将其与Snap集成的实际尝试。如你所见,我在定义__ doQuery__函数时遇到了问题,它应该返回一个字符串isbn:

代码语言:javascript
复制
{-# 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"

如果能帮上我的忙,我将不胜感激。如果有不清楚的地方,请让我知道,我会更新问题。

EN

回答 2

Stack Overflow用户

发布于 2012-10-02 22:52:07

MathematicalOrchid是正确的,对您的问题最简单的答案是在openLocalState调用上使用liftIO。

但是从更广泛的角度来看,snaplet-acid-state包已经为您完成了这里所做的工作,所以我建议您直接使用它。存储库还包括一个演示如何使用它的example application

票数 1
EN

Stack Overflow用户

发布于 2012-10-02 16:44:47

我不知道您正在使用的包是什么,但是看起来问题很简单,openLocalState是一个IO操作,但是您的类型签名要求它是一个Initializer操作。

修复它可能和在其中填充一个对liftIO的调用一样简单。不过我不是很确定...我不知道这些类型中的每一个都来自哪个模块。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12683835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档