%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1998
%
\section[PatSyn]{@PatSyn@: Pattern synonyms}
\begin{code}
module PatSyn (
PatSyn, mkPatSyn,
patSynId, patSynType, patSynArity, patSynIsInfix,
patSynArgs, patSynArgTys, patSynTyDetails,
patSynWrapper, patSynMatcher,
patSynExTyVars, patSynSig, patSynInstArgTys
) where
#include "HsVersions.h"
import Type
import Name
import Outputable
import Unique
import Util
import BasicTypes
import FastString
import Var
import Id
import TcType
import HsBinds( HsPatSynDetails(..) )
import qualified Data.Data as Data
import qualified Data.Typeable
import Data.Function
\end{code}
Pattern synonym representation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider the following pattern synonym declaration
pattern P x = MkT [x] (Just 42)
where
data T a where
MkT :: (Show a, Ord b) => [b] -> a -> T a
so pattern P has type
b -> T (Maybe t)
with the following typeclass constraints:
provides: (Show (Maybe t), Ord b)
requires: (Eq t, Num t)
In this case, the fields of MkPatSyn will be set as follows:
psArgs = [x :: b]
psArity = 1
psInfix = False
psUnivTyVars = [t]
psExTyVars = [b]
psTheta = ((Show (Maybe t), Ord b), (Eq t, Num t))
psOrigResTy = T (Maybe t)
%************************************************************************
%* *
\subsection{Pattern synonyms}
%* *
%************************************************************************
\begin{code}
data PatSyn
= MkPatSyn {
psId :: Id,
psUnique :: Unique,
psMatcher :: Id,
psWrapper :: Maybe Id,
psArgs :: [Var],
psArity :: Arity,
psInfix :: Bool,
psUnivTyVars :: [TyVar],
psExTyVars :: [TyVar],
psTheta :: (ThetaType, ThetaType),
psOrigResTy :: Type
}
deriving Data.Typeable.Typeable
\end{code}
%************************************************************************
%* *
\subsection{Instances}
%* *
%************************************************************************
\begin{code}
instance Eq PatSyn where
(==) = (==) `on` getUnique
(/=) = (/=) `on` getUnique
instance Ord PatSyn where
(<=) = (<=) `on` getUnique
(<) = (<) `on` getUnique
(>=) = (>=) `on` getUnique
(>) = (>) `on` getUnique
compare = compare `on` getUnique
instance Uniquable PatSyn where
getUnique = psUnique
instance NamedThing PatSyn where
getName = getName . psId
instance Outputable PatSyn where
ppr = ppr . getName
instance OutputableBndr PatSyn where
pprInfixOcc = pprInfixName . getName
pprPrefixOcc = pprPrefixName . getName
instance Data.Data PatSyn where
toConstr _ = abstractConstr "PatSyn"
gunfold _ _ = error "gunfold"
dataTypeOf _ = mkNoRepType "PatSyn"
\end{code}
%************************************************************************
%* *
\subsection{Construction}
%* *
%************************************************************************
\begin{code}
mkPatSyn :: Name
-> Bool
-> [Var]
-> [TyVar]
-> [TyVar]
-> ThetaType
-> ThetaType
-> Type
-> Id
-> Maybe Id
-> PatSyn
mkPatSyn name declared_infix orig_args
univ_tvs ex_tvs
prov_theta req_theta
orig_res_ty
matcher wrapper
= MkPatSyn {psId = id, psUnique = getUnique name,
psUnivTyVars = univ_tvs, psExTyVars = ex_tvs,
psTheta = (prov_theta, req_theta),
psInfix = declared_infix,
psArgs = orig_args,
psArity = length orig_args,
psOrigResTy = orig_res_ty,
psMatcher = matcher,
psWrapper = wrapper }
where
pat_ty = mkSigmaTy univ_tvs req_theta $
mkSigmaTy ex_tvs prov_theta $
mkFunTys (map varType orig_args) orig_res_ty
id = mkLocalId name pat_ty
\end{code}
\begin{code}
patSynId :: PatSyn -> Id
patSynId = psId
patSynType :: PatSyn -> Type
patSynType = psOrigResTy
patSynIsInfix :: PatSyn -> Bool
patSynIsInfix = psInfix
patSynArity :: PatSyn -> Arity
patSynArity = psArity
patSynArgs :: PatSyn -> [Var]
patSynArgs = psArgs
patSynArgTys :: PatSyn -> [Type]
patSynArgTys = map varType . patSynArgs
patSynTyDetails :: PatSyn -> HsPatSynDetails Type
patSynTyDetails ps = case (patSynIsInfix ps, patSynArgTys ps) of
(True, [left, right]) -> InfixPatSyn left right
(_, tys) -> PrefixPatSyn tys
patSynExTyVars :: PatSyn -> [TyVar]
patSynExTyVars = psExTyVars
patSynSig :: PatSyn -> ([TyVar], [TyVar], (ThetaType, ThetaType))
patSynSig ps = (psUnivTyVars ps, psExTyVars ps, psTheta ps)
patSynWrapper :: PatSyn -> Maybe Id
patSynWrapper = psWrapper
patSynMatcher :: PatSyn -> Id
patSynMatcher = psMatcher
patSynInstArgTys :: PatSyn -> [Type] -> [Type]
patSynInstArgTys ps inst_tys
= ASSERT2( length tyvars == length inst_tys
, ptext (sLit "patSynInstArgTys") <+> ppr ps $$ ppr tyvars $$ ppr inst_tys )
map (substTyWith tyvars inst_tys) arg_tys
where
(univ_tvs, ex_tvs, _) = patSynSig ps
arg_tys = map varType (psArgs ps)
tyvars = univ_tvs ++ ex_tvs
\end{code}