{-# LANGUAGE DeriveDataTypeable
, DeriveGeneric
, ExistentialQuantification
, FlexibleContexts
, GADTs #-}
module Unbound.Generics.LocallyNameless.Name
(
Name(..)
, isFreeName
, string2Name
, s2n
, makeName
, name2String
, name2Integer
, AnyName(..)
) where
import Control.DeepSeq (NFData(..))
import Data.Typeable (Typeable, gcast, typeOf)
import GHC.Generics (Generic)
data Name a = Fn String !Integer
| Bn !Integer !Integer
deriving (Eq, Ord, Typeable, Generic)
instance NFData (Name a) where
rnf (Fn s n) = rnf s `seq` rnf n `seq` ()
rnf (Bn i j) = rnf i `seq` rnf j `seq` ()
isFreeName :: Name a -> Bool
isFreeName (Fn _ _) = True
isFreeName _ = False
string2Name :: String -> Name a
string2Name s = makeName s 0
s2n :: String -> Name a
s2n = string2Name
makeName :: String -> Integer -> Name a
makeName = Fn
name2Integer :: Name a -> Integer
name2Integer (Fn _ i) = i
name2Integer (Bn _ _) = error "Internal Error: cannot call name2Integer for bound names"
name2String :: Name a -> String
name2String (Fn s _) = s
name2String (Bn _ _) = error "Internal Error: cannot call name2String for bound names"
instance Show (Name a) where
show (Fn "" n) = "_" ++ (show n)
show (Fn x 0) = x
show (Fn x n) = x ++ (show n)
show (Bn x y) = show x ++ "@" ++ show y
data AnyName where
AnyName :: Typeable a => Name a -> AnyName
instance Show AnyName where
show (AnyName nm) = show nm
instance Eq AnyName where
(AnyName n1) == (AnyName n2) = case gcast n2 of
Just n2' -> n1 == n2'
Nothing -> False
instance Ord AnyName where
compare (AnyName n1) (AnyName n2) = case compare (typeOf n1) (typeOf n2) of
EQ -> case gcast n2 of
Just n2' -> compare n1 n2'
Nothing -> error "Equal type representations, but gcast failed in comparing two AnyName values"
ord -> ord