{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module TCRError where
import Control.Monad.Reader
import Control.Monad.Error
import Database.TokyoCabinet
(
TCM
, runTCM
, new
, OpenMode(..)
, TCDB
, HDB
, BDB
, FDB
)
import Database.TokyoCabinet.Storable
import qualified Database.TokyoCabinet as TC
newtype TCRError tc e a =
TCRError { runTCRError :: ErrorT e (ReaderT tc TCM) a}
deriving (Monad, MonadReader tc, MonadError e)
runTCRE :: TCRError tc e a -> tc -> TCM (Either e a)
runTCRE = runReaderT . runErrorT . runTCRError
liftT :: (Error e) => TCM a -> TCRError tc e a
liftT = TCRError . lift . lift
open :: (TCDB tc) => String -> [OpenMode] -> TCRError tc String ()
open name mode = do tc <- ask
res <- liftT $ TC.open tc name mode
if res then return () else throwError "open failed"
close :: (TCDB tc) => TCRError tc String ()
close = ask >>= liftT . TC.close >>= \res ->
if res then return () else throwError "close failed"
put :: (TCDB tc) => String -> String -> TCRError tc String ()
put key val = do tc <- ask
res <- liftT $ TC.put tc key val
if res then return () else throwError "put failed"
get :: (TCDB tc) => String -> TCRError tc String (Maybe String)
get key = do tc <- ask
liftT $ TC.get tc key
kvstore :: (TCDB tc) => [(String, String)] -> TCRError tc String ()
kvstore kv = do open "abcd.tch" [OREADER]
mapM_ (uncurry put) kv
close
main :: IO ()
main = runTCM $ do h <- new :: TCM BDB
let kv = [("foo", "100"), ("bar", "200")]
flip runTCRE h $ catchError (kvstore kv) (\e -> error e)
>> return ()