{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Data.Comp.Param.Multi.FreshM
(
FreshM,
Name,
withName,
nameCoerce,
evalFreshM
) where
import Control.Monad.Reader
newtype FreshM a = FreshM{unFreshM :: Reader Int a}
deriving (Monad, Functor, Applicative)
newtype Name i = Name Int
deriving Eq
instance Show (Name i) where
show (Name x) = names !! x
where baseNames = ['a'..'z']
names = map (:[]) baseNames ++ names' 1
names' n = map (: show n) baseNames ++ names' (n + 1)
instance Ord (Name i) where
compare (Name x) (Name y) = compare x y
nameCoerce :: Name i -> Name j
nameCoerce (Name x) = Name x
withName :: (Name i -> FreshM a) -> FreshM a
withName m = do name <- FreshM (asks Name)
FreshM $ local ((+) 1) $ unFreshM $ m name
evalFreshM :: FreshM a -> a
evalFreshM (FreshM m) = runReader m 0