Add Coercion.lhs
[ghc-hetmet.git] / compiler / types / Coercion.lhs
1 \r
2  Module for type coercions, as in System FC.\r
3 \r
4 Coercions are represented as types, and their kinds tell what types the \r
5 coercion works on. \r
6 \r
7 The coercion kind constructor is a special TyCon that must always be saturated\r
8 \r
9   typeKind (symCoercion type) :: TyConApp CoercionTyCon{...} [type, type]\r
10 \r
11 \begin{code}\r
12 module Coercion (\r
13         Coercion,\r
14  \r
15         mkCoKind, mkReflCoKind, splitCoercionKind_maybe, splitCoercionKind,\r
16         coercionKind, coercionKinds, coercionKindPredTy,\r
17 \r
18         -- Equality predicates\r
19         isEqPred, mkEqPred, getEqPredTys, isEqPredTy,  \r
20 \r
21         -- Coercion transformations\r
22         mkSymCoercion, mkTransCoercion,\r
23         mkLeftCoercion, mkRightCoercion, mkInstCoercion, mkAppCoercion,\r
24         mkForAllCoercion, mkFunCoercion, mkInstsCoercion, mkUnsafeCoercion,\r
25         mkNewTypeCoercion, mkAppsCoercion,\r
26 \r
27         splitNewTypeRepCo_maybe, decomposeCo,\r
28 \r
29         unsafeCoercionTyCon, symCoercionTyCon,\r
30         transCoercionTyCon, leftCoercionTyCon, \r
31         rightCoercionTyCon, instCoercionTyCon -- needed by TysWiredIn\r
32        ) where \r
33 \r
34 #include "HsVersions.h"\r
35 \r
36 import TypeRep\r
37 import Type       ( Type, Kind, PredType, substTyWith, mkAppTy, mkForAllTy,\r
38                     mkFunTy, splitAppTy_maybe, splitForAllTy_maybe, coreView,\r
39                     kindView, mkTyConApp, isCoercionKind, isEqPred, mkAppTys\r
40                   )\r
41 import TyCon      ( TyCon, tyConArity, mkCoercionTyCon, isNewTyCon,\r
42                     newTyConRhs, newTyConCo, \r
43                     isCoercionTyCon, isCoercionTyCon_maybe )\r
44 import Var        ( Var, TyVar, isTyVar, tyVarKind )\r
45 import Name       ( BuiltInSyntax(..), Name, mkWiredInName, tcName )\r
46 import OccName    ( mkOccNameFS )\r
47 import PrelNames  ( symCoercionTyConKey, \r
48                     transCoercionTyConKey, leftCoercionTyConKey,\r
49                     rightCoercionTyConKey, instCoercionTyConKey, \r
50                     unsafeCoercionTyConKey, gHC_PRIM\r
51                   )\r
52 import Util       ( lengthIs, snocView )\r
53 import Unique     ( hasKey )\r
54 import BasicTypes ( Arity )\r
55 import Outputable\r
56 \r
57 \r
58 \r
59 ------------------------------\r
60 decomposeCo :: Arity -> Coercion -> [Coercion]\r
61 -- (decomposeCo 3 c) = [right (left (left c)), right (left c), right c]\r
62 decomposeCo n co\r
63   = go n co []\r
64   where\r
65     go 0 co cos = cos\r
66     go n co cos = go (n-1) (mkLeftCoercion co)\r
67                            (mkRightCoercion co : cos)\r
68 \r
69 ------------------------------\r
70 \r
71 -------------------------------------------------------\r
72 -- and some coercion kind stuff\r
73 \r
74 isEqPredTy (PredTy pred) = isEqPred pred\r
75 isEqPredTy other         = False\r
76 \r
77 mkEqPred :: (Type, Type) -> PredType\r
78 mkEqPred (ty1, ty2) = EqPred ty1 ty2\r
79 \r
80 getEqPredTys :: PredType -> (Type,Type)\r
81 getEqPredTys (EqPred ty1 ty2) = (ty1, ty2)\r
82 getEqPredTys other            = pprPanic "getEqPredTys" (ppr other)\r
83 \r
84 mkCoKind :: Type -> Type -> CoercionKind\r
85 mkCoKind ty1 ty2 = PredTy (EqPred ty1 ty2)\r
86 \r
87 mkReflCoKind :: Type -> CoercionKind\r
88 mkReflCoKind ty = mkCoKind ty ty\r
89 \r
90 splitCoercionKind :: CoercionKind -> (Type, Type)\r
91 splitCoercionKind co | Just co' <- kindView co = splitCoercionKind co'\r
92 splitCoercionKind (PredTy (EqPred ty1 ty2))    = (ty1, ty2)\r
93 \r
94 splitCoercionKind_maybe :: Kind -> Maybe (Type, Type)\r
95 splitCoercionKind_maybe co | Just co' <- kindView co = splitCoercionKind_maybe co'\r
96 splitCoercionKind_maybe (PredTy (EqPred ty1 ty2)) = Just (ty1, ty2)\r
97 splitCoercionKind_maybe other = Nothing\r
98 \r
99 isCoVar :: Var -> Bool\r
100 isCoVar tv = isTyVar tv && isCoercionKind (tyVarKind tv)\r
101 \r
102 type Coercion     = Type\r
103 type CoercionKind = Kind        -- A CoercionKind is always of form (ty1 :=: ty2)\r
104 \r
105 coercionKind :: Coercion -> (Type, Type)\r
106 --      c :: (t1 :=: t2)\r
107 -- Then (coercionKind c) = (t1,t2)\r
108 \r
109 coercionKind (TyVarTy a) | isCoVar a = splitCoercionKind (tyVarKind a)\r
110                          | otherwise = let t = (TyVarTy a) in (t, t)\r
111 coercionKind (AppTy ty1 ty2) \r
112   = let (t1, t2) = coercionKind ty1\r
113         (s1, s2) = coercionKind ty2 in\r
114     (mkAppTy t1 s1, mkAppTy t2 s2)\r
115 coercionKind (TyConApp tc args)\r
116   | Just (ar, rule) <- isCoercionTyCon_maybe tc \r
117   = if length args >= ar \r
118     then splitCoercionKind (rule args)\r
119     else pprPanic ("arity/arguments mismatch in coercionKind:") \r
120              (ppr ar $$ ppr tc <+> ppr args)\r
121   | otherwise\r
122   = let (lArgs, rArgs) = coercionKinds args in\r
123     (TyConApp tc lArgs, TyConApp tc rArgs)\r
124 coercionKind (FunTy ty1 ty2) \r
125   = let (t1, t2) = coercionKind ty1\r
126         (s1, s2) = coercionKind ty2 in\r
127     (mkFunTy t1 s1, mkFunTy t2 s2)\r
128 coercionKind (ForAllTy tv ty) \r
129   = let (ty1, ty2) = coercionKind ty in\r
130     (ForAllTy tv ty1, ForAllTy tv ty2)\r
131 coercionKind (NoteTy _ ty) = coercionKind ty\r
132 coercionKind (PredTy (EqPred c1 c2)) \r
133   = let k1 = coercionKindPredTy c1\r
134         k2 = coercionKindPredTy c2 in\r
135     (k1,k2)\r
136 coercionKind (PredTy (ClassP cl args)) \r
137   = let (lArgs, rArgs) = coercionKinds args in\r
138     (PredTy (ClassP cl lArgs), PredTy (ClassP cl rArgs))\r
139 coercionKind (PredTy (IParam name ty))\r
140   = let (ty1, ty2) = coercionKind ty in\r
141     (PredTy (IParam name ty1), PredTy (IParam name ty2))\r
142 \r
143 coercionKindPredTy :: Coercion -> CoercionKind\r
144 coercionKindPredTy c = let (t1, t2) = coercionKind c in mkCoKind t1 t2\r
145 \r
146 coercionKinds :: [Coercion] -> ([Type], [Type])\r
147 coercionKinds tys = unzip $ map coercionKind tys\r
148 \r
149 -------------------------------------\r
150 -- Coercion kind and type mk's\r
151 -- (make saturated TyConApp CoercionTyCon{...} args)\r
152 \r
153 mkCoercion coCon args = ASSERT( tyConArity coCon == length args ) \r
154                         TyConApp coCon args\r
155 \r
156 mkAppCoercion, mkFunCoercion, mkTransCoercion, mkInstCoercion :: Coercion -> Coercion -> Coercion\r
157 mkSymCoercion, mkLeftCoercion, mkRightCoercion :: Coercion -> Coercion\r
158 \r
159 mkAppCoercion    co1 co2 = mkAppTy co1 co2\r
160 mkAppsCoercion   co1 tys = foldl mkAppTy co1 tys\r
161 -- note that a TyVar should be used here, not a CoVar (nor a TcTyVar)\r
162 mkForAllCoercion tv  co  = ASSERT ( isTyVar tv ) mkForAllTy tv co\r
163 mkFunCoercion    co1 co2 = mkFunTy co1 co2\r
164 \r
165 mkSymCoercion co      \r
166   | Just co2 <- splitSymCoercion_maybe co = co2\r
167   | Just (co1, co2) <- splitAppCoercion_maybe co \r
168     -- should make this case better\r
169   = mkAppCoercion (mkSymCoercion co1) (mkSymCoercion co2)\r
170   | Just (co1, co2) <- splitTransCoercion_maybe co\r
171   = mkTransCoercion (mkSymCoercion co1) (mkSymCoercion co2)\r
172   | Just (co, ty) <- splitInstCoercion_maybe co\r
173   = mkInstCoercion (mkSymCoercion co) ty\r
174   | Just co <- splitLeftCoercion_maybe co\r
175   = mkLeftCoercion (mkSymCoercion co)\r
176   | Just co <- splitRightCoercion_maybe co\r
177   = mkRightCoercion (mkSymCoercion co)\r
178 mkSymCoercion (ForAllTy tv ty) = ForAllTy tv (mkSymCoercion ty)\r
179 -- for atomic types and constructors, we can just ignore sym since these\r
180 -- are reflexive coercions\r
181 mkSymCoercion (TyVarTy tv) \r
182   | isCoVar tv = mkCoercion symCoercionTyCon [TyVarTy tv]\r
183   | otherwise  = TyVarTy tv\r
184 mkSymCoercion co = mkCoercion symCoercionTyCon [co] \r
185                    -- this should not happen but does\r
186 \r
187 -- Smart constructors for left and right\r
188 mkLeftCoercion co \r
189   | Just (co', _) <- splitAppCoercion_maybe co = co'\r
190   | otherwise                            = mkCoercion leftCoercionTyCon [co]\r
191 \r
192 mkRightCoercion  co      \r
193   | Just (co1, co2) <- splitAppCoercion_maybe co = co2\r
194   | otherwise = mkCoercion rightCoercionTyCon [co]\r
195 \r
196 mkTransCoercion co1 co2 = mkCoercion transCoercionTyCon [co1, co2]\r
197 \r
198 mkInstCoercion  co ty = mkCoercion instCoercionTyCon  [co, ty]\r
199 \r
200 mkInstsCoercion co tys = foldl mkInstCoercion co tys\r
201 \r
202 splitSymCoercion_maybe :: Coercion -> Maybe Coercion\r
203 splitSymCoercion_maybe (TyConApp tc [co]) = \r
204   if tc `hasKey` symCoercionTyConKey\r
205   then Just co\r
206   else Nothing\r
207 splitSymCoercion_maybe co = Nothing\r
208 \r
209 splitAppCoercion_maybe :: Coercion -> Maybe (Coercion, Coercion)\r
210 -- Splits a coercion application, being careful *not* to split (left c), etc\r
211 -- which are really sytactic constructs, not applications\r
212 splitAppCoercion_maybe co  | Just co' <- coreView co = splitAppCoercion_maybe co'\r
213 splitAppCoercion_maybe (FunTy ty1 ty2)   = Just (TyConApp funTyCon [ty1], ty2)\r
214 splitAppCoercion_maybe (AppTy ty1 ty2)   = Just (ty1, ty2)\r
215 splitAppCoercion_maybe (TyConApp tc tys) \r
216    | not (isCoercionTyCon tc)\r
217    = case snocView tys of\r
218        Just (tys', ty') -> Just (TyConApp tc tys', ty')\r
219        Nothing          -> Nothing\r
220 splitAppCoercion_maybe co = Nothing\r
221 \r
222 splitTransCoercion_maybe :: Coercion -> Maybe (Coercion, Coercion)\r
223 splitTransCoercion_maybe (TyConApp tc [ty1, ty2]) \r
224  = if tc `hasKey` transCoercionTyConKey then\r
225        Just (ty1, ty2)\r
226    else\r
227        Nothing\r
228 splitTransCoercion_maybe other = Nothing\r
229 \r
230 splitInstCoercion_maybe :: Coercion -> Maybe (Coercion, Type)\r
231 splitInstCoercion_maybe (TyConApp tc [ty1, ty2])\r
232  = if tc `hasKey` instCoercionTyConKey then\r
233        Just (ty1, ty2)\r
234     else\r
235        Nothing\r
236 splitInstCoercion_maybe other = Nothing\r
237 \r
238 splitLeftCoercion_maybe :: Coercion -> Maybe Coercion\r
239 splitLeftCoercion_maybe (TyConApp tc [co])\r
240  = if tc `hasKey` leftCoercionTyConKey then\r
241        Just co\r
242    else\r
243        Nothing\r
244 splitLeftCoercion_maybe other = Nothing\r
245 \r
246 splitRightCoercion_maybe :: Coercion -> Maybe Coercion\r
247 splitRightCoercion_maybe (TyConApp tc [co])\r
248  = if tc `hasKey` rightCoercionTyConKey then\r
249        Just co\r
250    else\r
251        Nothing\r
252 splitRightCoercion_maybe other = Nothing\r
253 \r
254 -- Unsafe coercion is not safe, it is used when we know we are dealing with\r
255 -- bottom, which is the one case in which it is safe\r
256 mkUnsafeCoercion :: Type -> Type -> Coercion\r
257 mkUnsafeCoercion ty1 ty2 \r
258   = mkCoercion unsafeCoercionTyCon [ty1, ty2]\r
259 \r
260 \r
261 -- make the coercion associated with a newtype\r
262 mkNewTypeCoercion :: Name -> TyCon -> [TyVar] -> Type -> TyCon\r
263 mkNewTypeCoercion name tycon tvs rhs_ty \r
264   = ASSERT (length tvs == tyConArity tycon)\r
265     mkCoercionTyCon name (tyConArity tycon) rule\r
266   where\r
267     rule args = mkCoKind (substTyWith tvs args rhs_ty) (TyConApp tycon args)\r
268 \r
269 --------------------------------------\r
270 -- Coercion Type Constructors...\r
271 \r
272 -- Example.  The coercion ((sym c) (sym d) (sym e))\r
273 -- will be represented by (TyConApp sym [c, sym d, sym e])\r
274 -- If sym c :: p1=q1\r
275 --    sym d :: p2=q2\r
276 --    sym e :: p3=q3\r
277 -- then ((sym c) (sym d) (sym e)) :: (p1 p2 p3)=(q1 q2 q3)\r
278 --\r
279 -- (mkKindingFun f) is given the args [c, sym d, sym e]\r
280 mkKindingFun :: ([Type] -> (Type, Type, [Type])) -> [Type] -> Kind\r
281 mkKindingFun f args = \r
282   let (ty1, ty2, rest) = f args in \r
283   let (argtys1, argtys2) = unzip (map coercionKind rest) in\r
284   mkCoKind (mkAppTys ty1 argtys1) (mkAppTys ty2 argtys2)\r
285         \r
286 \r
287 symCoercionTyCon, transCoercionTyCon, leftCoercionTyCon, rightCoercionTyCon, instCoercionTyCon :: TyCon\r
288 -- Each coercion TyCon is built with the special CoercionTyCon record and\r
289 -- carries its won kinding rule.  Such CoercionTyCons must be fully applied\r
290 -- by any TyConApp in which they are applied, however they may also be over\r
291 -- applied (see example above) and the kinding function must deal with this.\r
292 symCoercionTyCon = \r
293   mkCoercionTyCon symCoercionTyConName 1 (mkKindingFun flipCoercionKindOf)\r
294   where\r
295     flipCoercionKindOf (co:rest) = (ty2, ty1, rest)\r
296         where\r
297           (ty1, ty2) = coercionKind co\r
298 \r
299 transCoercionTyCon = \r
300   mkCoercionTyCon transCoercionTyConName 2 (mkKindingFun composeCoercionKindsOf)\r
301   where\r
302     composeCoercionKindsOf (co1:co2:rest) = (a1, r2, rest)\r
303       where\r
304         (a1, r1) = coercionKind co1\r
305         (a2, r2) = coercionKind co2 \r
306 \r
307 leftCoercionTyCon =\r
308   mkCoercionTyCon leftCoercionTyConName 1 (mkKindingFun leftProjectCoercionKindOf)\r
309   where\r
310     leftProjectCoercionKindOf (co:rest) = (ty1, ty2, rest)\r
311       where\r
312         (ty1,ty2) = fst (splitCoercionKindOf co)\r
313 \r
314 rightCoercionTyCon =\r
315   mkCoercionTyCon rightCoercionTyConName 1 (mkKindingFun rightProjectCoercionKindOf)\r
316   where\r
317     rightProjectCoercionKindOf (co:rest) = (ty1, ty2, rest)\r
318       where\r
319         (ty1,ty2) = snd (splitCoercionKindOf co)\r
320 \r
321 splitCoercionKindOf :: Type -> ((Type,Type), (Type,Type))\r
322 -- Helper for left and right.  Finds coercion kind of its input and\r
323 -- returns the left and right projections of the coercion...\r
324 --\r
325 -- if c :: t1 s1 :=: t2 s2 then splitCoercionKindOf c = ((t1, t2), (s1, s2))\r
326 splitCoercionKindOf co\r
327   | Just (ty1, ty2) <- splitCoercionKind_maybe (coercionKindPredTy co)\r
328   , Just (ty_fun1, ty_arg1) <- splitAppTy_maybe ty1\r
329   , Just (ty_fun2, ty_arg2) <- splitAppTy_maybe ty2\r
330   = ((ty_fun1, ty_fun2),(ty_arg1, ty_arg2))\r
331 \r
332 instCoercionTyCon \r
333   =  mkCoercionTyCon instCoercionTyConName 2 (mkKindingFun instCoercionKind)\r
334   where\r
335     instantiateCo t s =\r
336       let Just (tv, ty) = splitForAllTy_maybe t in\r
337       substTyWith [tv] [s] ty\r
338 \r
339     instCoercionKind (co1:ty:rest) = (instantiateCo t1 ty, instantiateCo t2 ty, rest)\r
340       where (t1, t2) = coercionKind co1\r
341 \r
342 unsafeCoercionTyCon \r
343   = mkCoercionTyCon unsafeCoercionTyConName 2 (mkKindingFun unsafeCoercionKind)\r
344   where\r
345    unsafeCoercionKind (ty1:ty2:rest) = (ty1,ty2,rest) \r
346         \r
347 --------------------------------------\r
348 -- ...and their names\r
349 \r
350 mkCoConName occ key coCon = mkWiredInName gHC_PRIM (mkOccNameFS tcName occ)\r
351                             key Nothing (ATyCon coCon) BuiltInSyntax\r
352 \r
353 transCoercionTyConName = mkCoConName FSLIT("trans") transCoercionTyConKey transCoercionTyCon\r
354 symCoercionTyConName   = mkCoConName FSLIT("sym") symCoercionTyConKey symCoercionTyCon\r
355 leftCoercionTyConName  = mkCoConName FSLIT("left") leftCoercionTyConKey leftCoercionTyCon\r
356 rightCoercionTyConName = mkCoConName FSLIT("right") rightCoercionTyConKey rightCoercionTyCon\r
357 instCoercionTyConName  = mkCoConName FSLIT("inst") instCoercionTyConKey instCoercionTyCon\r
358 unsafeCoercionTyConName = mkCoConName FSLIT("CoUnsafe") unsafeCoercionTyConKey unsafeCoercionTyCon\r
359 \r
360 \r
361 \r
362 -- this is here to avoid module loops\r
363 splitNewTypeRepCo_maybe :: Type -> Maybe (Type, Coercion)  \r
364 -- Sometimes we want to look through a recursive newtype, and that's what happens here\r
365 -- It only strips *one layer* off, so the caller will usually call itself recursively\r
366 -- Only applied to types of kind *, hence the newtype is always saturated\r
367 splitNewTypeRepCo_maybe ty \r
368   | Just ty' <- coreView ty = splitNewTypeRepCo_maybe ty'\r
369 splitNewTypeRepCo_maybe (TyConApp tc tys)\r
370   | isNewTyCon tc \r
371   = ASSERT( tys `lengthIs` tyConArity tc )      -- splitNewTypeRepCo_maybe only be applied \r
372                                                 --      to *types* (of kind *)\r
373         case newTyConRhs tc of\r
374           (tvs, rep_ty) -> \r
375               ASSERT( length tvs == length tys )\r
376               Just (substTyWith tvs tys rep_ty, mkTyConApp co_con tys)\r
377   where\r
378     co_con = maybe (pprPanic "splitNewTypeRepCo_maybe" (ppr tc)) id (newTyConCo tc)\r
379 \r
380 splitNewTypeRepCo_maybe other = Nothing\r
381 \end{code}