{-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE CPP #-} #if __GLASGOW_HASKELL__ >=704 {-# LANGUAGE Safe #-} #elif __GLASGOW_HASKELL__ >=702 {-# LANGUAGE Trustworthy #-} #endif -- | Variables, de Bruijn indices and names. module RERE.Var where import Data.String (IsString (..)) #if !MIN_VERSION_base(4,8,0) import Data.Foldable (Foldable) import Data.Traversable (Traversable) #endif -- | 'Var' is essentially 'Maybe'. data Var a = B -- ^ bound | F a -- ^ free variable. deriving (Eq, Ord, Show, Functor, Foldable, Traversable) -- | Analogue of 'maybe' for 'Var'. unvar :: r -> (a -> r) -> Var a -> r unvar n _ B = n unvar _ j (F x) = j x -- | Swap variables. swapVar :: Var (Var a) -> Var (Var a) swapVar (F (F a)) = F (F a) swapVar (F B) = B swapVar B = F B instance IsString a => IsString (Var a) where fromString = F . fromString -- | Names carry information used in pretty-printing, -- but otherwise they all 'compare' 'EQ'ual. data Name = N String [Char] instance Show Name where showsPrec d (N n sfx) | null sfx = showsPrec d n | otherwise = showParen (d > 10) $ showString "N " . showsPrec 11 n . showChar ' ' . showsPrec 11 sfx instance Eq Name where _ == _ = True instance Ord Name where compare _ _ = EQ instance IsString Name where fromString n = N n [] -- | Make a name for derivative binding (adds subindex). derivativeName :: Char -> Name -> Name derivativeName c (N n cs) = N n (cs ++ [c])