sequor-0.2.3: lib/Helper/Atom.hs
{-# LANGUAGE GeneralizedNewtypeDeriving
, NoMonomorphismRestriction
, BangPatterns #-}
module Helper.Atom
( MonadAtoms (..)
, AtomTable (..)
, Atoms
, AtomsT
, empty
, evalAtoms
, evalAtomsT
, runAtoms
, runAtomsT
)
where
import Control.Monad.State
import Control.Monad.Identity
import qualified Data.Map as Map
import qualified Data.IntMap as IntMap
import qualified Data.Binary as B
import qualified Helper.Text as Text
type Txt = Text.Txt
data AtomTable = T { lastID :: !Int
, to :: Map.Map Txt Int
, from :: IntMap.IntMap Txt }
deriving (Eq,Show)
instance B.Binary AtomTable where
put t = do B.put (lastID t)
B.put (to t)
B.put (from t)
get = do liftM3 T B.get B.get B.get
class Monad m => MonadAtoms m where
toAtom :: Txt -> m Int
maybeToAtom :: Txt -> m (Maybe Int)
fromAtom :: Int -> m Txt
table :: m AtomTable
instance Monad m => MonadAtoms (AtomsT m) where
toAtom x = AtomsT $ do
t <- get
case Map.lookup x (to t) of
Just j -> return $! j
Nothing -> do
let i = lastID t
i' = i + 1
!t' = t { lastID = i'
, to = Map.insert x i (to t)
, from = IntMap.insert i x (from t) }
put t'
return $! lastID t
maybeToAtom x =
AtomsT $ do
t <- get
return . Map.lookup x . to $ t
fromAtom i = AtomsT $ do
t <- get
return $ (from t) IntMap.! i
table = AtomsT get
empty :: AtomTable
empty = T 0 Map.empty IntMap.empty
runAtomsT :: AtomsT t t1 -> AtomTable -> t (t1, AtomTable)
runAtomsT (AtomsT x) s = runStateT x s
runAtoms :: Atoms t -> AtomTable -> (t, AtomTable)
runAtoms (Atoms x) s = runIdentity (runAtomsT x s)
evalAtoms :: Atoms t -> t
evalAtoms = fst . flip runAtoms empty
evalAtomsT :: (Monad m) => AtomsT m a -> m a
evalAtomsT = liftM fst . flip runAtomsT empty
newtype AtomsT m r = AtomsT (StateT AtomTable m r)
deriving (Functor,Monad,MonadTrans,MonadIO)
newtype Atoms r = Atoms (AtomsT Identity r)
deriving (Functor,Monad,MonadAtoms)