-- © 2001, 2002, 2003 Peter Thiemann {-| The Types module aims at providing a representation for (first-order) monomorphic Haskell types. Two type representations are equal if and only if the represented types have identical definitions. Thus a type representation consists of a type term and the smallest list of all (data or newtype) definitions needed either in the type term or in another definition. The list of definitions is sorted to make representations unique. The main use of type representations is to provide a type index for storing Haskell values externally and for reading them back into a running program without sacrificing type safety. Just reading them back with the @Read@ class is not sufficient because * @Read@ does not distinguish between @Int@ and @Integer@, @Float@ and @Double@y * @Read@ cannot avoid accidental matches of constructor names Meanwhile, the 'Data.Typeable' class of GHC provides an encoding with similar goals. -} module WASH.CGI.Types where import Maybe -- | A type specification consists of a type representation 'TyRep' and a list of -- type declarations. data TySpec = TS TyRep [TyDecl] -- declarations sorted! deriving (Read, Show, Eq) -- | A type representation is built from base types, type variables, tuples, and -- references to data-defined types. data TyRep = TRBase String | TRVar String | TRTuple [TyRep] | TRData String [TyRep] deriving (Read, Show, Eq) -- | A data declaration consists of the name of the data type, a list of type -- variables, and a list of constructor representations. data TyDecl = TD String [String] [ConRep] deriving (Read, Show, Eq) -- | A constructor is represented by its name, a list of field names (if defined -- using record notation), and the list of its argument types data ConRep = CR String -- ctor name (Maybe [String]) -- field names [TyRep] -- field types deriving (Read, Show, Eq) class Types a where ty :: a -> TySpec instance Types () where ty i = TS (TRBase "()") [] instance Types Bool where ty i = TS (TRBase "Bool") [] instance Types Int where ty i = TS (TRBase "Int") [] instance Types Integer where ty i = TS (TRBase "Integer") [] --instance Types Rational where -- ty i = TS (TRBase "Rational") [] instance Types Double where ty d = TS (TRBase "Double") [] instance Types Float where ty d = TS (TRBase "Float") [] instance Types Char where ty c = TS (TRBase "Char") [] instance (Types a, Types b) => Types (a,b) where ty xy = TS (TRTuple [tra, trb]) (merge defsa defsb) where TS tra defsa = ty (fst xy) TS trb defsb = ty (snd xy) instance (Types a, Types b, Types c) => Types (a,b,c) where ty ~(xa,xb,xc) = TS (TRTuple [tra, trb, trc]) (merge (merge defsa defsb) defsc) where TS tra defsa = ty xa TS trb defsb = ty xb TS trc defsc = ty xc instance (Types a, Types b, Types c, Types d) => Types (a,b,c,d) where ty ~(xa,xb,xc,xd) = TS (TRTuple [tra, trb, trc, trd]) (merge (merge defsa defsb) (merge defsc defsd)) where TS tra defsa = ty xa TS trb defsb = ty xb TS trc defsc = ty xc TS trd defsd = ty xd instance (Types a, Types b, Types c, Types d, Types e) => Types (a,b,c,d,e) where ty ~(xa,xb,xc,xd,xe) = TS (TRTuple [tra, trb, trc, trd, tre]) (merges [defsa, defsb, defsc, defsd, defse]) where TS tra defsa = ty xa TS trb defsb = ty xb TS trc defsc = ty xc TS trd defsd = ty xd TS tre defse = ty xe instance (Types a) => Types [a] where ty xs = TS (TRData (tdName listDef) [tr]) (merge defs [listDef]) where TS tr defs = ty (head xs) listDef :: TyDecl listDef = TD "[]" ["a"] [CR "[]" Nothing [] ,CR ":" Nothing [TRVar "a" ,TRData (tdName listDef) [TRVar "a"]]] instance (Types a) => Types (Maybe a) where ty mx = TS (TRData (tdName maybeDef) [tr]) (merge defs [maybeDef]) where TS tr defs = ty (fromJust mx) -- fromJust (Just x) = x -- in Module Maybe maybeDef :: TyDecl maybeDef = TD "Maybe" ["a"][CR "Nothing" Nothing [] ,CR "Just" Nothing [TRVar "a"]] instance (Types a, Types b) => Types (Either a b) where ty xy = TS (TRData (tdName eitherDef) [tra, trb]) (merge (merge defsa defsb) [eitherDef]) where TS tra defsa = ty (fromLeft xy) TS trb defsb = ty (fromRight xy) fromLeft (Left x) = x fromRight (Right y) = y eitherDef :: TyDecl eitherDef = TD "Either" ["a", "b"] [CR "Left" Nothing [TRVar "a"] ,CR "Right" Nothing [TRVar "b"]] tdName (TD name _ _) = name merge :: [TyDecl] -> [TyDecl] -> [TyDecl] merge [] ys = ys merge xs [] = xs merge (x:xs) (y:ys) | x == y = x : merge xs ys | tdName x == tdName y = error ("Different types with identical name: " ++ tdName x) | tdName x <= tdName y = x : merge xs (y:ys) | otherwise = y : merge (x:xs) ys merges :: [[TyDecl]] -> [TyDecl] merges tss = foldr merge [] tss class TID a where tid :: a -> ShowS instance TID TySpec where tid (TS tyRep tyDecls) = tid tyRep . tid tyDecls instance TID a => TID [a] where tid [] = showChar '.' tid (x : xs) = showChar ',' . tid x . tid xs instance TID TyRep where tid (TRBase str) = showChar 'B' . shows str tid (TRVar str) = showChar 'V' . shows str tid (TRTuple tyReps) = showChar 'T' . tid tyReps tid (TRData str tyReps) = showChar 'D' . shows str . tid tyReps instance TID TyDecl where tid (TD name tyvars conreps) = shows name . shows tyvars . tid conreps instance TID ConRep where tid (CR ctorname mFields tyReps) = shows ctorname . shows mFields . tid tyReps