2014-03-04 7 views
0

LevelDB 라이브러리와 Snap 프레임 워크를 함께 사용하고 있습니다. 내가 가진 :Haskell : Snap 및 LevelDB를 멋지게 만들기

handleWords :: Handler App App() 
handleWords = do 
    words <- uses thedb $ \db -> $ get db def "words" 
    writeBS $ pack $ show words 

나에게 제공합니다 : No instance for (MonadResource IO) arising from a use of 'get'

어떤을

main :: IO() 
main = runResourceT $ do 
    db <- open "thedb" defaultOptions { createIfMissing = True } 
    liftIO $ serveSnaplet defaultConfig $ initWeb db 

지금 내 처리기에서, 나는 데이터베이스를 조회하기 위해 MonadResource IO 다시 연락하는 방법을 확실 해요 아이디어? 모나드 "스택"을 올바르게 만드는 방법에 대해 뭔가 빠져있는 것처럼 느껴집니다. 감사합니다

답변

3

MonadResource/ResourceT은 자원이 예외의 경우에 해제된다는 것을 보장하는 방식으로 희소 자원을 확보하는 한 가지 방법입니다. 또 다른 접근법은 bracket 패턴이며, the bracketSnap function을 통한 스냅에 의해 지원됩니다. 단지를 가정 open 기능을 제공하는 대신

  • :이 일부 스냅의 변화와 leveldb로 간단하게 만들 수있는

    import qualified Control.Monad.Trans.Resource as Res 
    bracketSnap Res.createInternalState Res.closeInternalState $ \resState -> do 
        let openAction = open "thedb" defaultOptions { createIfMissing = True } 
        db <- Res.runInternalState openAction resState 
    

    : 당신은 LevelDB에 필요한 ResourceT 컨텍스트를 만들려면이 사용할 수 있습니다 MonadResource 컨텍스트에는 Resource value을 반환하는 함수가있을 수 있습니다. 2.0 릴리스에서는이 조정을 지속적으로하고 있습니다.

  • 스냅은 MonadResource 또는 Resource 모나드 (불행히도 비슷한 이름을 가진 두 개의 개별 개념)에 대한 지원을 제공 할 수 있습니다.
0

Snap은 이것을 수행하기 위해 MonadResource 또는 Resource를 지원할 필요가 없습니다. 당신은 잘못된 방향으로 모나드 변압기 구성을하고 있습니다. 유형을 살펴 보는 것이 도움이 될 것입니다.

serveSnaplet :: Config Snap AppConfig -> SnapletInit b b -> IO() 
runResourceT :: MonadBaseControl IO m => ResourceT m a -> m a 

따라서 ResourceT가 필요한 위치에 IO를 배치하려고합니다. 당신은이 반대 방향으로 접근해야합니다. open "thedb" ... 호출을 애플리케이션의 초기화 프로그램에 liftIO로 넣습니다. 그러나 open은 MonadResource이므로 ResourceT 인스턴스를 사용하여 IO에 가져와야합니다. 그것은 다음과 같이 보일 것입니다 :

app = makeSnaplet "app" "An snaplet example application." Nothing $ do 
    ... 
    db <- liftIO $ runResourceT $ open "thedb" defaultOptions 

은 다음 앱 상태에서 DB 핸들을 저장하면 나중에 Handler의 MonadReader 또는 MonadState 인스턴스를 사용하여 검색 할 수 있습니다.

+0

아니요, 작동하지 않습니다. 'runResourceT' 블록을 종료 했으므로'db'는 즉시 닫힙니다. 당신이 제안한 코드는'withFile "foo"ReadMode return'와 유사합니다. –

+0

아, 맞아. 나는 다른 상황에서 그 패턴을 사용하는 데 익숙해졌고 runResourceT가 클린업을 강제한다는 것을 잊어 버렸다. – mightybyte