haskore-supercollider-0.1: src/Haskore/General/IdGenerator/Set.hs
{- | Identifier generator
Generates unique elements but elements can be declared as unused, again.
-}
module Haskore.General.IdGenerator.Set where
import Data.Set (Set)
import qualified Data.Set as Set
import Control.Monad.Trans.RWS(RWS, evalRWS, modify, get, ask, )
import Control.Monad (when, )
{- |
The generator is a reader+state monad
where the state consists of the allocated identifiers
and the reader source is the least element ever used.
-}
type T i a = RWS i () (Set i) a
run :: i -> T i a -> a
run start gen = fst $ evalRWS gen start Set.empty
{- |
Reserve a new id.
-}
alloc :: (Ord i, Enum i) => T i i
alloc =
do start <- ask
allocated <- get
let newId = head $ filter (not . flip Set.member allocated) [start ..]
modify (Set.insert newId)
return newId
{- |
Deallocate an id.
-}
free :: (Ord i, Enum i) => i -> T i ()
free oldId =
do allocated <- get
when (not $ Set.member oldId allocated)
(error "IdGeneratorSet.free: deallocated free identifier")
modify (Set.delete oldId)