TypedIds.hs

module TypedIds where
import Maybe(isJust)

Haskell declaration introduce names in two name spaces. Type classes and types live in one name space. Values (functions, data constructors) live in another name space.

data NameSpace = ClassOrTypeNames | ValueNames     deriving (Eq,Ord,Show)

Identifiers can denote many different types of entities. It is clear from the defining occurence of an identifier what type of entity it denotes.

The type IdTy can be seen as a refinement of NameSpace. From the use of an identifier, we can tell what name space it refers to, but not the exact type of entity, hence the need for two different types.

data IdTy i 
    = Value 
    | FieldOf i (TypeInfo i)
    | MethodOf i Int [i] -- name of class, number of superclasses, names of all methods
    | ConstrOf i (TypeInfo i)
    | Class Int [i] -- number of superclasses, names of all methods
    | Type (TypeInfo i)
    | Assertion -- P-Logic assertion name
    | Property  -- P-Logic property name
        deriving (Eq,{-Ord,-}Show,Read)
        -- These structures contain a lot of redundancy, so we shouldn't really
	-- use any comparison operations on them.

data ConInfo i = ConInfo 
    { conName :: i
    , conArity :: Int
    , conFields :: Maybe [i] -- length agrees with conArity
    } deriving (Eq,{-Ord,-}Show,Read)

data DefTy     = Newtype | Data | Synonym | Primitive
               deriving (Eq,Ord,Show,Read)

data TypeInfo i = TypeInfo
    { defType       :: Maybe DefTy
    , constructors  :: [ConInfo i]
    , fields        :: [i]
    } deriving (Eq,{-Ord,-}Show,Read)

blankTypeInfo = TypeInfo { defType = Nothing, constructors = [], fields = [] }



instance Functor ConInfo where
    fmap f c = c { conName = f (conName c),
		   conFields = fmap (map f) (conFields c) }

instance Functor TypeInfo where
    fmap f t = t { constructors = map (fmap f) (constructors t)
                 , fields = map f (fields t)
                 }

instance Functor IdTy where
    fmap f (FieldOf x tyInfo)   = FieldOf (f x) (fmap f tyInfo)
    fmap f (MethodOf x n xs)      = MethodOf (f x) n (map f xs)
    fmap f (ConstrOf t tyInfo)  = ConstrOf (f t) (fmap f tyInfo)
    fmap _ Value                = Value
    fmap f (Class n xs)         = Class n (f `map` xs)
    fmap f (Type tyInfo)        = Type (fmap f tyInfo)
    fmap _ Assertion            = Assertion
    fmap _ Property             = Property

class HasNameSpace t where
    namespace :: t -> NameSpace

instance HasNameSpace (IdTy id) where
    namespace Value         = ValueNames
    namespace (FieldOf {}) = ValueNames
    namespace (MethodOf {}) = ValueNames
    namespace (ConstrOf {}) = ValueNames
    namespace (Class {})    = ClassOrTypeNames
    namespace (Type {})     = ClassOrTypeNames
    namespace Assertion     = ValueNames -- hmm
    namespace Property      = ValueNames -- hmm


-- owner :: IdTy i -> Maybe i
owner (FieldOf dt  _) = Just dt
owner (MethodOf cl _ _) = Just cl
owner (ConstrOf dt _) = Just dt
owner _               = Nothing


-- isSubordinate :: IdTy i -> Bool
isSubordinate = isJust . owner

-- belongsTo :: idTy i -> i -> Bool
idty `belongsTo` t = owner idty == Just t

isAssertion Assertion = True
isAssertion Property  = True
isAssertion _         = False

isClassOrType,isValue :: HasNameSpace t => t -> Bool
isClassOrType   = (== ClassOrTypeNames) . namespace
isValue         = (== ValueNames)       . namespace

class HasIdTy i t | t->i where
  idTy :: t -> IdTy i

instance HasIdTy i (IdTy i) where idTy = id
--instance HasNameSpace NameSpace where namespace = id

Plain-text version of TypedIds.hs | Valid HTML?