{-# 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