Fine grained STRICT pragmas
Currently STRICT pragmas can only be applied at a module scale. It'd be more useful to have more fine-grained STRICT pragmas that can be applied to functions in a module. For example, here's function from GHC:
tidyType :: TidyEnv -> Type -> Type
tidyType _ (LitTy n) = LitTy n
tidyType env (TyVarTy tv) = TyVarTy (tidyTyCoVarOcc env tv)
tidyType env (TyConApp tycon tys) = let args = tidyTypes env tys
in args `seqList` TyConApp tycon args
tidyType env (AppTy fun arg) = (AppTy $! (tidyType env fun)) $! (tidyType env arg)
tidyType env ty@(FunTy _ arg res) = let { !arg' = tidyType env arg
; !res' = tidyType env res }
in ty { ft_arg = arg', ft_res = res' }
tidyType env (ty@(ForAllTy{})) = mkForAllTys' (zip tvs' vis) $! tidyType env' body_ty
where
(tvs, vis, body_ty) = splitForAllTys' ty
(env', tvs') = tidyVarBndrs env tvs
tidyType env (CastTy ty co) = (CastTy $! tidyType env ty) $! (tidyCo env co)
tidyType env (CoercionTy co) = CoercionTy $! (tidyCo env co)
Every let binding has a bang, and function applications are done strictly
($!
). If we supported {-# STRICT tidyType #-}
this would be much simpler:
(NOTE: I'm not sure if -XStrict
turns normal applications into strict
applications, below I'm assuming it does)
{-# STRICT tidyType #-}
tidyType :: TidyEnv -> Type -> Type
tidyType _ (LitTy n) = LitTy n
tidyType env (TyVarTy tv) = TyVarTy (tidyTyCoVarOcc env tv)
tidyType env (TyConApp tycon tys) = TyConApp tycon (seqListId (tidyTypes env tys))
tidyType env (AppTy fun arg) = AppTy (tidyType env fun) (tidyType env arg)
tidyType env ty@(FunTy _ arg res) = ty { ft_arg = tidyType env arg, ft_res = tidyType env res }
tidyType env (ty@(ForAllTy{})) = mkForAllTys' (zip tvs' vis) (tidyType env' body_ty)
where
(~tvs, ~vis, ~body_ty) = splitForAllTys' ty
(~env', ~tvs') = tidyVarBndrs env tvs
tidyType env (CastTy ty co) = CastTy (tidyType env ty) (tidyCo env co)
tidyType env (CoercionTy co) = CoercionTy (tidyCo env co)