monad-atom (empty) → 0.1.0
raw patch · 4 files changed
+192/−0 lines, 4 filesdep +basedep +binarydep +bytestringsetup-changed
Dependencies added: base, binary, bytestring, containers, mtl
Files
- Control/Monad/Atom.hs +101/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- monad-atom.cabal +59/−0
+ Control/Monad/Atom.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE GeneralizedNewtypeDeriving + , NoMonomorphismRestriction + , BangPatterns #-}+module Control.Monad.Atom+ ( MonadAtom (..)+ , AtomTable+ , Atom+ , AtomT+ , empty+ , evalAtom+ , evalAtomT+ , runAtom+ , runAtomT+ )+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 Data.ByteString.Lazy as BS++type Blob = BS.ByteString++data AtomTable = T { lastID :: {-# UNPACK #-} !Int + , to :: Map.Map Blob Int + , from :: IntMap.IntMap Blob } + 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 => MonadAtom m where+ -- | Monadically convert the argument into an atom (represented as an Int)+ toAtom :: B.Binary a => a -> m Int+ -- | Monadically convert the argument into an atom, but only if + -- the corresponding atom has already been created+ maybeToAtom :: B.Binary a => a -> m (Maybe Int)+ -- | Monadically convert an atom represented as an Int to its + -- corresponding object+ fromAtom :: B.Binary a => Int -> m a+++instance Monad m => MonadAtom (AtomT m) where+ toAtom x = AtomT $ do+ let b = B.encode x+ t <- get+ case Map.lookup b (to t) of+ Just j -> return $! j+ Nothing -> do + let i = lastID t+ i' = i + 1 + !t' = t { lastID = i'+ , to = Map.insert b i (to t) + , from = IntMap.insert i b (from t) }+ put t'+ return $! lastID t++ maybeToAtom x = + AtomT $ do+ t <- get+ return . Map.lookup (B.encode x) . to $ t+ + fromAtom i = AtomT $ do+ t <- get+ return . B.decode $ (from t) IntMap.! i++table = AtomT get++empty :: AtomTable+empty = T 0 Map.empty IntMap.empty++runAtomT :: AtomT t t1 -> AtomTable -> t (t1, AtomTable)+runAtomT (AtomT x) s = runStateT x s++runAtom :: Atom t -> AtomTable -> (t, AtomTable)+runAtom (Atom x) s = runIdentity (runAtomT x s)+++evalAtom :: Atom t -> t+evalAtom = fst . flip runAtom empty++evalAtomT :: (Monad m) => AtomT m a -> m a+evalAtomT = liftM fst . flip runAtomT empty++newtype AtomT m r = AtomT (StateT AtomTable m r)+ deriving (Functor,Monad,MonadTrans,MonadIO)++newtype Atom r = Atom (AtomT Identity r)+ deriving (Functor,Monad,MonadAtom)++example :: [String]+example = evalAtom $ do + xs <- mapM toAtom . map show $ [1,2,3,1,2,3]+ zs <- mapM fromAtom xs + return zs
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2011, Grzegorz Chrupała++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Grzegorz Chrupała nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ monad-atom.cabal view
@@ -0,0 +1,59 @@+-- monad-atom.cabal auto-generated by cabal init. For additional+-- options, see+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.+-- The name of the package.+Name: monad-atom++-- The package version. See the Haskell package versioning policy+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for+-- standards guiding when and how versions should be incremented.+Version: 0.1.0++-- A short (one-line) description of the package.+Synopsis: Monadically convert objects to unique atoms and back.++-- A longer description of the package.+Description: Monadically convert objects to unique atoms and back.++-- The license under which the package is released.+License: BSD3++-- The file containing the license text.+License-file: LICENSE++-- The package author(s).+Author: Grzegorz Chrupała++-- An email address to which users can send suggestions, bug reports,+-- and patches.+Maintainer: gchrupala@lsv.uni-saarland.de++-- A copyright notice.+-- Copyright: ++Category: Control++Build-type: Simple++-- Extra files to be distributed with the package, such as examples or+-- a README.+-- Extra-source-files: ++-- Constraint on the version of Cabal needed to build this package.+Cabal-version: >=1.2+++Library+ -- Modules exported by the library.+ Exposed-modules: Control.Monad.Atom+ + -- Packages needed in order to build this package.+ Build-depends: base >= 3 && < 5, bytestring >= 0.9, binary >= 0.5,+ containers >= 0.4, mtl >= 2.0++ -- Modules not exported by this package.+ -- Other-modules: + + -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.+ -- Build-tools: +