{-# LANGUAGE UndecidableInstances, OverloadedStrings, TupleSections, RankNTypes, FlexibleInstances, LambdaCase #-} module Funcons.Operations.Values where import qualified Data.Map as M import qualified Data.Vector as V import qualified Data.Set as S import qualified Data.MultiSet as MS import qualified Data.Char as C import Data.Text (Text, pack, unpack) import Data.List (intercalate) import Data.Maybe (fromJust,isJust) import Data.String import Control.Monad (liftM2) import Control.Arrow ((***)) type Name = Text type MVar = String -- | -- This datatype provides a number of builtin value types. -- The type `t` is expected to be a super-type of `Values t`, -- such that there is a projection and injection between `t` and `Values t`, -- (see 'HasValues') data Values t = ADTVal Name [t] | Atom String | ComputationType (ComputationTypes t) | Float Double | IEEE_Float_32 Float | IEEE_Float_64 Double | Int Integer | Map (ValueMaps (Values t)) | Multiset (MS.MultiSet (Values t)) | Nat Integer | Rational Rational | Set (ValueSets (Values t)) | Vector (ValueVectors (Values t)) | VAny -- used whenever funcon terms may have holes in them -- currently only the case in "downwards" flowing signals | ValSeq [t] -- represents a multitude of values deriving (Eq,Ord,Show,Read) ascii_cons = "ascii-character" unicode_cons = "unicode-character" tuple :: HasValues t => [Values t] -> Values t tuple = ADTVal "tuple" . map inject list :: HasValues t => [Values t] -> Values t list = ADTVal "list" . map inject vector :: HasValues t => [Values t] -> Values t vector = ADTVal "vector" . map inject multi :: HasValues t => [t] -> Values t multi = ValSeq multi_ :: HasValues t => [Values t] -> Values t multi_ = multi . map inject instance HasValues t => IsString (Values t) where fromString = ADTVal "list" . map (inject . mk_unicode_characters) type ValueMaps t = M.Map t [t] type ValueSets t = S.Set t type ValueVectors t = V.Vector t -- | Postfix operators for specifying sequences. data SeqSortOp = StarOp | PlusOp | QuestionMarkOp deriving (Show, Eq, Ord, Read) -- | Computation type /S=>T/ reflects a type of term -- whose given value is of type /S/ and result is of type /T/. data ComputationTypes t = Type (Types t) -- | /=>T/ | ComputesType (Types t) -- | /S=>T/ | ComputesFromType (Types t) (Types t) deriving (Ord,Eq,Show, Read) -- | Representation of builtin types. data Types t= ADTs | ADT Name [t] | AnnotatedType (Types t) SeqSortOp | AsciiCharacters | ISOLatinCharacters | BMPCharacters | Atoms | IntegersFrom Integer -- value-dependent type | IntegersUpTo Integer | Characters | Complement (Types t) | ComputationTypes | EmptyType | IEEEFloats IEEEFormats | Integers | Intersection (Types t) (Types t) | Naturals | NullType | Rationals | Types | UnicodeCharacters | Union (Types t) (Types t) | Values deriving (Ord,Eq,Show,Read) sets :: HasValues t => Types t -> Types t sets t = ADT "sets" [injectT t] multisets :: HasValues t => Types t -> Types t multisets t = ADT "multisets" [injectT t] maps :: HasValues t => t -> t -> Types t maps k v = ADT "maps" [k, v] vectors :: HasValues t => Types t -> Types t vectors t = ADT "vectors" [injectT t] class HasValues t where project :: t -> Maybe (Values t) inject :: Values t -> t class HasComputationTypes t where projectCT :: t -> Maybe (ComputationTypes t) injectCT :: ComputationTypes t -> t class HasTypes t where projectT :: t -> Maybe (Types t) injectT :: Types t -> t instance HasValues t => HasComputationTypes t where projectCT v = project v >>= \case ComputationType t -> Just t _ -> Nothing injectCT = inject . ComputationType instance HasComputationTypes t => HasTypes t where projectT ct = projectCT ct >>= \case Type t -> Just t _ -> Nothing injectT = injectCT . Type data IEEEFormats = Binary32 | Binary64 deriving (Enum,Show,Eq,Ord,Read) -- Specialised version of 'fmap' vmap :: (Ord b) => (a -> b) -> Values a -> Values b vmap f v = case v of ADTVal nm ts -> ADTVal nm (map f ts) Atom a -> Atom a ComputationType t -> ComputationType (fmap f t) Float f -> Float f IEEE_Float_32 f -> IEEE_Float_32 f IEEE_Float_64 f -> IEEE_Float_64 f Int i -> Int i Map m -> Map $ M.fromList $ map (vmap f *** fmap (vmap f)) $ M.assocs m Set s -> Set $ S.map (vmap f) s Multiset ms -> Multiset $ MS.map (vmap f) ms Nat n -> Nat n Rational r -> Rational r Vector v -> Vector $ V.map (vmap f) v VAny -> VAny ValSeq ts -> ValSeq (map f ts) traverseV :: (Ord b, Monad m, HasValues a, HasValues b) => (a -> m b) -> Values a -> m (Values b) traverseV f = traverseVM f (mapM f) traverseVM :: (Ord b, Monad m, HasValues a, HasValues b) => (a -> m b) -> ([a] -> m [b]) -> Values a -> m (Values b) traverseVM f fs v = case v of ADTVal nm vs -> return . ADTVal nm =<< fs vs Atom a -> return $ Atom a ComputationType t -> return . ComputationType =<< traverseCTM f fs t Float f -> return $ Float f IEEE_Float_32 f -> return $ IEEE_Float_32 f IEEE_Float_64 f -> return $ IEEE_Float_64 f Int i -> return $ Int i Map m -> do let (keys, valss) = unzip (M.assocs m) keys' <- map (fromJust . project) <$> fs (map inject keys) vals' <- map (map (fromJust . project)) <$> mapM (fs . map inject) valss return (Map $ M.fromList $ zip keys' vals') Set s -> return . Set . S.fromList . map (fromJust . project) =<< fs (map inject $ S.toList s) Multiset ms -> return . Multiset . MS.fromList . map (fromJust . project) =<< fs (map inject $ MS.toList ms) Nat n -> return $ Nat n Rational r -> return $ Rational r Vector v -> return . Vector . V.fromList . map (fromJust . project) =<< fs (map inject $ V.toList v) VAny -> return VAny ValSeq ts -> ValSeq <$> fs ts traverseT :: (Ord b, Monad m, HasValues a, HasValues b) => (a -> m b) -> Types a -> m (Types b) traverseT f = traverseTM f (mapM f) traverseTM :: (Ord b, Monad m, HasValues a, HasValues b) => (a -> m b) -> ([a] -> m [b]) -> Types a -> m (Types b) traverseTM f fs t = case t of ADTs -> return ADTs ADT nm ts -> return . ADT nm =<< fs ts AsciiCharacters -> return AsciiCharacters ISOLatinCharacters -> return ISOLatinCharacters BMPCharacters -> return BMPCharacters Atoms -> return Atoms AnnotatedType ty op -> AnnotatedType <$> traverseTM f fs ty <*> return op Characters -> return Characters ComputationTypes -> return ComputationTypes Complement t -> Complement <$> traverseTM f fs t IntegersFrom f -> return (IntegersFrom f) IntegersUpTo f -> return (IntegersUpTo f) Intersection t1 t2 -> Intersection <$> traverseTM f fs t1 <*> traverseTM f fs t2 NullType -> return NullType EmptyType -> return EmptyType IEEEFloats i -> return (IEEEFloats i) Integers -> return Integers Naturals -> return Naturals Rationals -> return Rationals Types -> return Types UnicodeCharacters -> return UnicodeCharacters Union t1 t2 -> Union <$> traverseTM f fs t1 <*> traverseTM f fs t2 Values -> return Values traverseCTM f fs t = case t of Type t -> Type <$> traverseTM f fs t ComputesType t -> ComputesType <$> traverseTM f fs t ComputesFromType ty ty2 -> ComputesFromType <$> traverseTM f fs ty <*> traverseTM f fs ty2 structVcompare :: (Monoid m, HasValues a, HasValues b) => (a -> b -> Maybe m) -> Values a -> Values b -> Maybe (Maybe m) structVcompare comp = structVMcompare comp comps where comps xs ys | length xs == length ys = fmap mconcat $ sequence $ zipWith comp xs ys | otherwise = Nothing structCTMcompare :: (Monoid m, HasValues a, HasValues b) => (a -> b -> Maybe m) -> ([a] -> [b] -> Maybe m) -> ComputationTypes a -> ComputationTypes b -> (Maybe (Maybe m)) structCTMcompare comp comps va vb = case (va,vb) of (Type x, Type y) -> structTMcompare comp comps x y (Type _,_) -> Nothing (_, Type _) -> Nothing (ComputesType x, ComputesType y) -> structTMcompare comp comps x y (ComputesType _, _) -> Nothing (_, ComputesType _) -> Nothing (ComputesFromType x y, ComputesFromType x' y') -> liftM2 mappend (structTMcompare comp comps x x') (structTMcompare comp comps y y') structVMcompare :: (Monoid m, HasValues b, HasValues a) => (a -> b -> Maybe m) -> ([a] -> [b] -> Maybe m) -> Values a -> Values b -> Maybe (Maybe m) structVMcompare comp comps va vb = case (va, vb) of (ADTVal nm1 vs1, ADTVal nm2 vs2) | nm1 == nm2 -> Just $ comps vs1 vs2 (ADTVal _ _, _) -> Nothing (_, ADTVal _ _) -> Nothing (Atom x, Atom y) | x == y -> Just (Just mempty) (Atom _, _) -> Nothing (_, Atom _) -> Nothing (ComputationType x ,ComputationType y) -> structCTMcompare comp comps x y (_, ComputationType x) -> Nothing (ComputationType _, _) -> Nothing (Float x, Float y) | x == y -> Just (Just mempty) (Float _, _) -> Nothing (_, Float _) -> Nothing (IEEE_Float_32 x, IEEE_Float_32 y) | x == y -> Nothing (IEEE_Float_32 _, _) -> Nothing (_, IEEE_Float_32 _) -> Nothing (IEEE_Float_64 x, IEEE_Float_64 y) | x == y -> Nothing (IEEE_Float_64 _, _) -> Nothing (_, IEEE_Float_64 _) -> Nothing (Int x, Int y) | x == y -> Just (Just mempty) (Int _, _) -> Nothing (_, Int _) -> Nothing (Map m1, Map m2) -> Just $ liftM2 mappend (comps' (M.keys m1) (M.keys m2)) (comps' (map list $ M.elems m1) (map list $ M.elems m2)) (Map _, _) -> Nothing (_, Map _) -> Nothing (Set x, Set y) -> Just $ comps' (S.toList x) (S.toList y) (Set _, _) -> Nothing (_, Set _) -> Nothing (Multiset x, Multiset y) -> Just $ comps (map inject $ MS.toList x) (map inject $ MS.toList y) (Multiset _, _) -> Nothing (_, Multiset _) -> Nothing (Nat x, Nat y) | x == y -> Just (Just mempty) (Nat _, _) -> Nothing (_, Nat _) -> Nothing (Rational x, Rational y) | x == y -> Just (Just mempty) (Rational _, _) -> Nothing (_, Rational _) -> Nothing (Vector x, Vector y) -> Just $ comps (map inject $ V.toList x) (map inject $ V.toList y) (VAny, VAny) -> Just (Just mempty) (_, VAny) -> Nothing (VAny, _) -> Nothing (ValSeq ts, ValSeq ts') -> Just (comps ts ts') (ValSeq _, _) -> Nothing (_, ValSeq _) -> Nothing where comps' xs ys = comps (map inject xs) (map inject ys) structTMcompare :: (Monoid m, HasValues a, HasValues b) => (a -> b -> Maybe m) -> ([a] -> [b] -> Maybe m) -> Types a -> Types b -> Maybe (Maybe m) structTMcompare comp comps ta tb = case (ta, tb) of (ADTs, ADTs) -> Just (Just mempty) (ADTs, _) -> Nothing (_, ADTs) -> Nothing (ADT nm1 ts, ADT nm2 ts') | nm1 == nm2 -> Just $ comps ts ts' (ADT _ _, _) -> Nothing (_, ADT _ _) -> Nothing (Atoms, Atoms) -> Just (Just mempty) (Atoms, _) -> Nothing (_, Atoms) -> Nothing (AsciiCharacters, AsciiCharacters) -> Just (Just mempty) (AsciiCharacters, _) -> Nothing (_, AsciiCharacters) -> Nothing (ISOLatinCharacters, ISOLatinCharacters) -> Just (Just mempty) (ISOLatinCharacters, _) -> Nothing (_, ISOLatinCharacters) -> Nothing (BMPCharacters, BMPCharacters) -> Just (Just mempty) (BMPCharacters, _) -> Nothing (_, BMPCharacters) -> Nothing (AnnotatedType t1 op1, AnnotatedType t2 op2) | op1 == op2 -> structTMcompare comp comps t1 t2 (AnnotatedType _ _, _) -> Nothing (_, AnnotatedType _ _) -> Nothing (Characters, Characters) -> Just (Just mempty) (Characters, _) -> Nothing (_, Characters) -> Nothing (Complement x, Complement y) -> structTMcompare comp comps x y (_, Complement _) -> Nothing (Complement _, _) -> Nothing (ComputationTypes, ComputationTypes)-> Just (Just mempty) (_, ComputationTypes) -> Nothing (ComputationTypes, _) -> Nothing (IntegersFrom mx, IntegersFrom mx') | mx == mx' -> Just (Just mempty) (IntegersFrom _, _) -> Nothing (_, IntegersFrom _) -> Nothing (IntegersUpTo mx, IntegersUpTo mx') | mx == mx' -> Just (Just mempty) (IntegersUpTo _, _) -> Nothing (_, IntegersUpTo _) -> Nothing (EmptyType, EmptyType) -> Just (Just mempty) (_, EmptyType) -> Nothing (EmptyType, _) -> Nothing (IEEEFloats x, IEEEFloats y) | x ==y-> Just (Just mempty) (IEEEFloats _, _) -> Nothing (_, IEEEFloats _) -> Nothing (Integers, Integers) -> Just (Just mempty) (Integers, _) -> Nothing (_, Integers) -> Nothing (Intersection x y, Intersection x' y') -> liftM2 mappend (structTMcompare comp comps x x') (structTMcompare comp comps y y') (Intersection _ _, _) -> Nothing (_, Intersection _ _) -> Nothing (Naturals, Naturals) -> Just (Just mempty) (_, Naturals) -> Nothing (Naturals, _) -> Nothing (NullType, NullType) -> Just (Just mempty) (_, NullType) -> Nothing (NullType,_) -> Nothing (Rationals, Rationals) -> Just (Just mempty) (Rationals, _) -> Nothing (_, Rationals) -> Nothing (Types, Types) -> Just (Just mempty) (_, Types) -> Nothing (Types, _) -> Nothing (UnicodeCharacters, UnicodeCharacters) -> Just (Just mempty) (UnicodeCharacters, _) -> Nothing (_, UnicodeCharacters) -> Nothing (Union u v, Union x y) -> liftM2 mappend (structTMcompare comp comps u x) (structTMcompare comp comps v y) (Union _ _, _) -> Nothing (_, Union _ _) -> Nothing (Values, Values) -> Just (Just mempty) instance Functor Types where fmap f t = case t of ADT nm ts -> ADT nm (map f ts) ADTs -> ADTs AsciiCharacters -> AsciiCharacters ISOLatinCharacters -> ISOLatinCharacters BMPCharacters -> BMPCharacters Atoms -> Atoms AnnotatedType ty op -> AnnotatedType (fmap f ty) op Complement t1 -> Complement (fmap f t1) ComputationTypes -> ComputationTypes IntegersFrom p -> IntegersFrom p IntegersUpTo p -> IntegersUpTo p Characters -> Characters EmptyType -> EmptyType IEEEFloats b -> IEEEFloats b Integers -> Integers Intersection t1 t2 -> Intersection (fmap f t1) (fmap f t2) Naturals -> Naturals NullType -> NullType Rationals -> Rationals Types -> Types UnicodeCharacters -> UnicodeCharacters Union t1 t2 -> Union (fmap f t1) (fmap f t2) Values -> Values instance Functor ComputationTypes where fmap f t = case t of Type t -> Type $ fmap f t ComputesType t -> ComputesType $ fmap f t ComputesFromType t1 t2 -> ComputesFromType (fmap f t1) (fmap f t2) instance Foldable Types where foldMap f fa = case fa of ADT _ ts -> foldMap f ts ADTs -> mempty AsciiCharacters -> mempty ISOLatinCharacters -> mempty BMPCharacters -> mempty Atoms -> mempty AnnotatedType ty op -> foldMap f ty Characters -> mempty Complement t1 -> foldMap f t1 ComputationTypes -> mempty IntegersUpTo q -> mempty IntegersFrom q -> mempty Intersection t1 t2 -> foldMap f t1 `mappend` foldMap f t2 EmptyType -> mempty IEEEFloats b -> mempty Integers -> mempty Naturals -> mempty NullType -> mempty Rationals -> mempty Types -> mempty UnicodeCharacters -> mempty Union t1 t2 -> foldMap f t1 `mappend` foldMap f t2 Values -> mempty instance Traversable Types where traverse f ta = case ta of ADTs -> pure ADTs ADT nm ts -> ADT nm <$> traverse f ts AsciiCharacters -> pure AsciiCharacters ISOLatinCharacters -> pure ISOLatinCharacters BMPCharacters -> pure BMPCharacters AnnotatedType ty op -> AnnotatedType <$> traverse f ty <*> pure op Atoms -> pure Atoms Characters -> pure Characters Complement t -> Complement <$> traverse f t ComputationTypes -> pure ComputationTypes IntegersFrom n -> pure $ IntegersFrom n IntegersUpTo n -> pure $ IntegersUpTo n EmptyType -> pure EmptyType IEEEFloats b -> pure $ IEEEFloats b Integers -> pure Integers Intersection t1 t2 -> Intersection <$> traverse f t1 <*> traverse f t2 Naturals -> pure Naturals NullType -> pure NullType Rationals -> pure Rationals Types -> pure Types UnicodeCharacters -> pure UnicodeCharacters Union t1 t2 -> Union <$> traverse f t1 <*> traverse f t2 Values -> pure Values downcastValueType :: Values t -> Types t downcastValueType (ComputationType (Type t)) = t downcastValueType (ComputationType (ComputesType t)) = t downcastValueType (ComputationType (ComputesFromType _ t)) = t downcastValueType _ = error "valueType: not a type" -- | Returns the /rational/ representation of a value if it is a subtype. -- Otherwise it returns the original value. upcastRationals :: Values t -> Values t upcastRationals (Nat n) = Rational (toRational n) upcastRationals (Int i) = Rational (toRational i) upcastRationals v = v -- | Returns the /integer/ representation of a value if it is a subtype. -- Otherwise it returns the original value. upcastIntegers :: Values t -> Values t upcastIntegers (Nat n) = Int n upcastIntegers v = v -- | Returns the /natural/ representation of a value if it is a subtype. -- Otherwise it returns the original value. upcastNaturals :: Values t -> Values t upcastNaturals (Int i) | i >= 0 = Nat i upcastNaturals v = v upcastCharacter :: HasValues t => Values t -> Maybe Char upcastCharacter (ADTVal c [v]) | Just (Int p) <- project v = Just (C.chr (fromInteger p)) upcastCharacter v = Nothing castType :: HasValues t => Values t -> Maybe (Types t) castType (ComputationType (Type ty)) = Just ty castType (ComputationType (ComputesType ty)) = Just ty castType (ComputationType (ComputesFromType _ ty)) = Just ty castType _ = Nothing -- numbers mk_integers :: Integer -> Values t mk_integers i | i >= 0 = mk_naturals i | otherwise = Int i mk_naturals :: Integer -> Values t mk_naturals = Nat mk_unicode_characters :: HasValues t => Char -> Values t mk_unicode_characters = downcast_unicode_characters -- | -- Checks whetDoes not check whether the `unicode-point` of downcast_unicode_characters :: HasValues t => Char -> Values t downcast_unicode_characters c = ADTVal unicode_cons [inject (Int (toInteger (C.ord c)))] --- Value specific (===) :: (HasValues t, Eq t {- UNNECESSARY CONSTRAINT -}) => Values t -> Values t -> Bool v1 === v2 = isGround v1 && isGround v2 && (v1 == v2) (=/=) :: (HasValues t, Eq t {- UNNECESSARY CONSTRAINT -}) => Values t -> Values t -> Bool v1 =/= v2 = isGround v1 && isGround v2 && (v1 /= v2) isGround :: HasValues t => Values t -> Bool isGround (ADTVal _ mv) = all (maybe False isGround . project) mv isGround (Atom _) = True isGround (Float _) = True isGround (IEEE_Float_32 _) = True isGround (IEEE_Float_64 _) = True isGround (Int _) = True isGround (Map m) = all (all isGround) (M.elems m) isGround (Multiset ms) = all isGround (MS.elems ms) isGround (Nat _) = True isGround (ComputationType _) = True isGround (Rational _) = True isGround (Set s) = all isGround (S.toList s) isGround (Vector v) = all isGround (V.toList v) isGround VAny = False isGround (ValSeq ts) = all (maybe False isGround . project) ts -- functions that check simple properties of funcons -- TODO: Some of these are used, and all are exported by Funcons.EDSL -- But are all of them still needed. E.g isId doesn't seem very useful now that ids are just strings. isNat ((Int _)) = True isNat _ = False isInt ((Int _)) = True isInt _ = False isEnv f = isMap f isMap ((Map _)) = True isMap _ = False isSet ((Set _)) = True isSet _ = False isString_ :: HasValues t => Values t -> Bool isString_ (ADTVal "list" vs) = not (null vs) && all (maybe False (isJust . upcastCharacter)) (map project vs) isString_ _ = False isType (ComputationType _) = True isType _ = False isVec ((Vector _)) = True isVec _ = False unString :: HasValues t => Values t -> String unString (ADTVal "list" vs) | Just vs' <- sequence (map (fmap upcastCharacter . project) vs) , all isJust vs' = map (\(Just c) -> c) vs' unString _ = error "unString" null__ :: Values t null__ = ADTVal "null" [] null_value__ :: Values t null_value__ = ADTVal "null-value" [] isNull :: Values t -> Bool isNull (ADTVal "null" _) = True isNull (ADTVal "null-value" _) = True isNull _ = False isDefinedVal :: Values t -> Bool isDefinedVal f = not (isNull f) set_ :: Ord t => [Values t] -> Values t set_ = Set . S.fromList ppValues :: HasValues t => (t -> String) -> Values t -> String ppValues showT v@(ADTVal "list" vs) | isString_ v, not (null vs) = show (unString v) | otherwise = "[" ++ showArgs_ (map showT vs) ++ "]" ppValues showT (ADTVal c []) = unpack c ppValues showT (ADTVal c vs) = unpack c ++ showArgs (map showT vs) ppValues showT (Atom c) = "atom("++ c ++")" ppValues showT (Float f) = show f -- rationals ppValues showT (IEEE_Float_32 f) = show f ppValues showT (IEEE_Float_64 d) = show d ppValues showT (Rational r) = show r ppValues showT (Int f) = show f ppValues showT (Nat f) = show f ppValues showT (Map m) = if M.null m then "map-empty" else "{" ++ key_values ++ "}" where key_values = intercalate ", " (map showKP $ M.assocs m) where showKP (k,vs) = ppValues showT k ++ " |-> " ++ case vs of [v] -> ppValues showT v _ -> showArgs (map (ppValues showT) vs) ppValues showT (Multiset s) = "{" ++ showArgs (map (ppValues showT) (MS.toList s)) ++ "}" ppValues showT (Set s) = "{" ++ showArgs (map (ppValues showT) (S.toList s)) ++ "}" ppValues showT (Vector v) = "vector" ++ showArgs (map (ppValues showT) (V.toList v)) ppValues showT (ComputationType ty) = ppComputationTypes showT ty ppValues showT VAny = "_" ppValues showT (ValSeq ts) = showArgs_ (map showT ts) ppComputationTypes :: HasValues t => (t -> String) -> ComputationTypes t -> String ppComputationTypes showT (Type t) = ppTypes showT t ppComputationTypes showT (ComputesType ty) = "=>" ++ ppTypes showT ty ppComputationTypes showT (ComputesFromType s t) = ppTypes showT s ++ "=>" ++ ppTypes showT t ppTypes :: HasValues t => (t -> String) -> Types t -> String ppTypes showT (AnnotatedType ty op) = ppTypes showT ty ++ ppOp op ppTypes showT (Complement ty) = "~(" ++ ppTypes showT ty ++ ")" ppTypes showT ComputationTypes = "computation-types" ppTypes showT NullType = "null-type" ppTypes showT Atoms = "atoms" ppTypes showT AsciiCharacters = "ascii-characters" ppTypes showT ISOLatinCharacters = "iso-latin-1-characters" ppTypes showT BMPCharacters = "basic-multilingual-plane-characters" ppTypes showT Characters = "characters" ppTypes showT (Intersection t1 t2) = "(" ++ ppTypes showT t1 ++ "&" ++ ppTypes showT t2 ++")" ppTypes showT (IntegersFrom n) = "integers-from(" ++ show n ++ ")" ppTypes showT (IntegersUpTo n) = "integers-to(" ++ show n ++ ")" ppTypes showT EmptyType = "empty-type" ppTypes showT (UnicodeCharacters) = "unicode-characters" ppTypes showT (Integers) = "integers" ppTypes showT (Values) = "values" ppTypes showT Types = "types" ppTypes showT ADTs = "algebraic-datatypes" ppTypes showT (ADT nm ts) = unpack nm ++ showArgs (map showT ts) ppTypes showT (IEEEFloats format) = "ieee-floats(" ++ show format ++ ")" ppTypes showT Naturals = "naturals" ppTypes showT Rationals = "rationals" ppTypes showT (Union ty1 ty2) = "(" ++ ppTypes showT ty1 ++ "|" ++ ppTypes showT ty2 ++")" ppOp :: SeqSortOp -> String ppOp StarOp = "*" ppOp PlusOp = "+" ppOp QuestionMarkOp = "?" showArgs :: [String] -> String showArgs args = "(" ++ showArgs_ args ++ ")" showArgs_ :: [String] -> String showArgs_ args = intercalate "," args