overeasy-0.1.0: src/Overeasy/Source.hs
{-# LANGUAGE DeriveAnyClass #-}
-- | See 'Source'.
module Overeasy.Source
( Source
, sourceSize
, sourceNew
, sourceAddInc
, sourceAdd
, sourceSkipInc
, sourceSkip
, sourcePeek
) where
import Control.DeepSeq (NFData)
import Control.Monad.State.Strict (State, modify', state)
import Data.Coerce (Coercible, coerce)
import GHC.Generics (Generic)
-- | A source of unique ids
data Source x = Source
{ sourceSize :: !Int
-- ^ How many ids have ever been created?
, sourceNextId :: !Int
} deriving stock (Eq, Show, Generic)
deriving anyclass (NFData)
-- | Creates a new 'Source' from a starting id
sourceNew :: Coercible x Int => x -> Source x
sourceNew = Source 0 . coerce
-- | Generates the next id from the source (purely)
sourceAddInc :: Coercible x Int => Source x -> (x, Source x)
sourceAddInc (Source s x) = (coerce x, Source (s + 1) (x + 1))
-- | Generates the next id from the source (statefully)
sourceAdd :: Coercible x Int => State (Source x) x
sourceAdd = state sourceAddInc
-- | Skips past the given id (purely)
sourceSkipInc :: Coercible x Int => x -> Source x -> Source x
sourceSkipInc y (Source s x) =
let z = coerce y
in Source (s + 1) (max x (z + 1))
-- | Skips past the given id (statefully)
sourceSkip :: Coercible x Int => x -> State (Source x) ()
sourceSkip = modify' . sourceSkipInc
-- | Peek at the next id
sourcePeek :: Coercible x Int => Source x -> x
sourcePeek = coerce . sourceNextId