curry-frontend-2.0.0: src/Base/TypeExpansion.hs
{- |
Module : $Header$
Description : Type expansion
Copyright : (c) 2016 Finn Teegen
License : BSD-3-clause
Maintainer : bjp@informatik.uni-kiel.de
Stability : experimental
Portability : portable
This module implements expansion of alias types in types and predicates.
-}
module Base.TypeExpansion
( module Base.TypeExpansion
) where
import qualified Data.Set.Extra as Set (map)
import Curry.Base.Ident
import Curry.Syntax
import Base.CurryTypes
import Base.Messages
import Base.Types
import Base.TypeSubst
import Env.Class
import Env.TypeConstructor
-- The function 'expandType' expands all type synonyms in a type
-- and also qualifies all type constructors with the name of the module
-- in which the type was defined. Similarly, 'expandPred' expands all
-- type synonyms in a predicate and also qualifies all class identifiers
-- with the name of the module in which the class was defined. The
-- function 'expandPredSet' minimizes the predicate set after expansion.
expandType :: ModuleIdent -> TCEnv -> Type -> Type
expandType m tcEnv ty = expandType' m tcEnv ty []
expandType' :: ModuleIdent -> TCEnv -> Type -> [Type] -> Type
expandType' m tcEnv (TypeConstructor tc) tys =
case qualLookupTypeInfo tc tcEnv of
[DataType tc' _ _ ] -> applyType (TypeConstructor tc') tys
[RenamingType tc' _ _ ] -> applyType (TypeConstructor tc') tys
[AliasType _ _ n ty] -> let (tys', tys'') = splitAt n tys
in applyType (expandAliasType tys' ty) tys''
_ -> case qualLookupTypeInfo (qualQualify m tc) tcEnv of
[DataType tc' _ _ ] -> applyType (TypeConstructor tc') tys
[RenamingType tc' _ _ ] -> applyType (TypeConstructor tc') tys
[AliasType _ _ n ty] -> let (tys', tys'') = splitAt n tys
in applyType (expandAliasType tys' ty) tys''
_ -> internalError $ "Base.TypeExpansion.expandType: " ++ show tc
expandType' m tcEnv (TypeApply ty1 ty2) tys =
expandType' m tcEnv ty1 (expandType m tcEnv ty2 : tys)
expandType' _ _ tv@(TypeVariable _) tys = applyType tv tys
expandType' _ _ tc@(TypeConstrained _ _) tys = applyType tc tys
expandType' m tcEnv (TypeArrow ty1 ty2) tys =
applyType (TypeArrow (expandType m tcEnv ty1) (expandType m tcEnv ty2)) tys
expandType' m tcEnv (TypeForall tvs ty) tys =
applyType (TypeForall tvs (expandType m tcEnv ty)) tys
expandPred :: ModuleIdent -> TCEnv -> Pred -> Pred
expandPred m tcEnv (Pred qcls ty) = case qualLookupTypeInfo qcls tcEnv of
[TypeClass ocls _ _] -> Pred ocls (expandType m tcEnv ty)
_ -> case qualLookupTypeInfo (qualQualify m qcls) tcEnv of
[TypeClass ocls _ _] -> Pred ocls (expandType m tcEnv ty)
_ -> internalError $ "Base.TypeExpansion.expandPred: " ++ show qcls
expandPredSet :: ModuleIdent -> TCEnv -> ClassEnv -> PredSet -> PredSet
expandPredSet m tcEnv clsEnv = minPredSet clsEnv . Set.map (expandPred m tcEnv)
expandPredType :: ModuleIdent -> TCEnv -> ClassEnv -> PredType -> PredType
expandPredType m tcEnv clsEnv (PredType ps ty) =
PredType (expandPredSet m tcEnv clsEnv ps) (expandType m tcEnv ty)
-- The functions 'expandMonoType' and 'expandPolyType' convert (qualified)
-- type expressions into (predicated) types and also expand all type synonyms
-- and qualify all type constructors during the conversion.
expandMonoType :: ModuleIdent -> TCEnv -> [Ident] -> TypeExpr -> Type
expandMonoType m tcEnv tvs = expandType m tcEnv . toType tvs
expandPolyType :: ModuleIdent -> TCEnv -> ClassEnv -> QualTypeExpr -> PredType
expandPolyType m tcEnv clsEnv =
normalize 0 . expandPredType m tcEnv clsEnv . toPredType []
-- The function 'expandConstrType' computes the predicated type for a data
-- or newtype constructor. Similar to 'toConstrType' from 'CurryTypes', the
-- type's context is restricted to those type variables which are free in
-- the argument types. However, type synonyms are expanded and type constructors
-- and type classes are qualified with the name of the module containing their
-- definition.
expandConstrType :: ModuleIdent -> TCEnv -> ClassEnv -> QualIdent -> [Ident]
-> [TypeExpr] -> PredType
expandConstrType m tcEnv clsEnv tc tvs tys =
normalize n $ expandPredType m tcEnv clsEnv pty
where n = length tvs
pty = toConstrType tc tvs tys
-- The function 'expandMethodType' converts the type of a type class method
-- Similar to function 'toMethodType' from 'CurryTypes', the implicit class
-- constraint is added to the method's type and the class' type variable is
-- assigned index 0. However, type synonyms are expanded and type constructors
-- and type classes are qualified with the name of the module containing their
-- definition.
expandMethodType :: ModuleIdent -> TCEnv -> ClassEnv -> QualIdent -> Ident
-> QualTypeExpr -> PredType
expandMethodType m tcEnv clsEnv qcls tv =
normalize 1 . expandPredType m tcEnv clsEnv . toMethodType qcls tv