knit-haskell-0.3.0.0: src/Knit/Effect/UnusedId.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
{-|
Module : Knit.Effect.UnusedId
Description : Wrapper around Polysemy.State for generating unused ids with a given prefix
Copyright : (c) Adam Conner-Sax 2019
License : BSD-3-Clause
Maintainer : adam_conner_sax@yahoo.com
Stability : experimental
-}
module Knit.Effect.UnusedId
(
-- * Effect
UnusedId
-- * actions
, getNextUnusedId
-- * interpretations
, runUnusedId
)
where
import qualified Polysemy as P
import qualified Polysemy.State as PS
import qualified Data.Map as M
import qualified Data.Text as T
import Data.Maybe ( fromMaybe )
-- | Type alias for the dictionary ('M.Map') of current last used id at each prefix.
type IdMap = M.Map T.Text Int
-- | Type alias for 'Polysemy.State' using "IdMap".
type UnusedId = PS.State IdMap
-- | Get an unused id with prefix as specified. Useful for figures, etc.
getNextUnusedId :: P.Member UnusedId r => T.Text -> P.Sem r T.Text
getNextUnusedId prefixT = do
idMap <- PS.get @IdMap
let nextId = fromMaybe 1 $ M.lookup prefixT idMap
PS.put $ M.insert prefixT (nextId + 1) idMap
return $ prefixT <> "_" <> (T.pack $ show nextId)
-- | Run the UnusedId effect and throw away the state.
runUnusedId :: P.Sem (UnusedId ': r) a -> P.Sem r a
runUnusedId = fmap snd . PS.runState M.empty