module Haskore.General.IdGenerator where
import Data.Set (Set)
import qualified Data.Set as Set
import Control.Monad.Trans.State(State, state, evalState, modify, get, )
import Control.Monad (when, )
import Data.Tuple.HT (mapFst, )
type T i a = State (St i) a
type St i = (Set i, i)
run :: i -> T i a -> a
run start gen = evalState gen (Set.empty, start)
alloc :: (Ord i, Enum i) => T i i
alloc =
state $ \(set, next) ->
if Set.null set
then (next, (set, succ next))
else let (newId, newSet) = Set.deleteFindMin set
in (newId, (newSet, next))
free :: (Ord i, Enum i) => i -> T i ()
free oldId =
do s <- get
when (isFree s oldId)
(error "IdGenerator.free: id freed twice")
modify (mapFst (Set.insert oldId))
modify reduce
reduce :: (Ord i, Enum i) => St i -> St i
reduce (set, next) =
if not (Set.null set) && Set.findMax set == pred next
then (Set.deleteMax set, pred next)
else (set, next)
isFree :: (Ord i) => St i -> i -> Bool
isFree (set,next) i = Set.member i set || i >= next
isValid :: (Ord i) => St i -> Bool
isValid (set,next) = Set.findMax set < next