2012-08-09 14:38:18 +00:00
|
|
|
|
2013-02-04 10:56:22 +00:00
|
|
|
module Types.Substitutions (subst,
|
|
|
|
occurs,
|
|
|
|
freeVars,
|
|
|
|
concretize,
|
|
|
|
rescheme,
|
2013-02-07 08:17:23 +00:00
|
|
|
generalize) where
|
2012-08-09 14:38:18 +00:00
|
|
|
|
2013-02-06 11:04:55 +00:00
|
|
|
import Ast
|
2012-12-25 08:39:18 +00:00
|
|
|
import Context
|
2012-08-09 14:38:18 +00:00
|
|
|
import Control.DeepSeq (NFData (..), deepseq)
|
|
|
|
import Control.Monad (liftM)
|
|
|
|
import Data.List (foldl')
|
|
|
|
import qualified Data.Set as Set
|
2012-12-25 08:39:18 +00:00
|
|
|
import qualified Data.Map as Map
|
2012-08-09 14:38:18 +00:00
|
|
|
import Guid
|
2012-11-23 04:30:37 +00:00
|
|
|
import Types.Types
|
2012-08-09 14:38:18 +00:00
|
|
|
|
2012-11-29 06:16:08 +00:00
|
|
|
class Subst a where
|
|
|
|
subst :: [(X,Type)] -> a -> a
|
|
|
|
|
|
|
|
instance Subst Type where
|
2012-12-25 08:39:18 +00:00
|
|
|
subst ss t =
|
|
|
|
case t of
|
|
|
|
VarT x -> case lookup x ss of
|
|
|
|
Nothing -> VarT x
|
|
|
|
Just (Super _) -> VarT x
|
|
|
|
Just t -> t
|
|
|
|
LambdaT t1 t2 -> LambdaT (subst ss t1) (subst ss t2)
|
|
|
|
ADT name ts -> ADT name (subst ss ts)
|
|
|
|
RecordT fs t -> RecordT (Map.map (subst ss) fs) (subst ss t)
|
|
|
|
EmptyRecord -> EmptyRecord
|
|
|
|
Super ts -> Super ts
|
2012-11-29 06:16:08 +00:00
|
|
|
|
|
|
|
instance Subst Scheme where
|
|
|
|
subst ss (Forall vs cs t) = Forall vs (subst ss cs) (subst ss t)
|
|
|
|
|
|
|
|
instance Subst Constraint where
|
|
|
|
subst ss (t1 :=: t2) = subst ss t1 :=: subst ss t2
|
|
|
|
subst ss (t :<: super) = subst ss t :<: super
|
|
|
|
subst ss (x :<<: poly) = x :<<: subst ss poly
|
|
|
|
|
2012-12-25 08:39:18 +00:00
|
|
|
instance Subst a => Subst (Context a) where
|
|
|
|
subst ss (C str span c) = C str span (subst ss c)
|
2012-11-29 06:16:08 +00:00
|
|
|
|
|
|
|
instance Subst a => Subst [a] where
|
|
|
|
subst ss as = map (subst ss) as
|
2012-08-09 14:38:18 +00:00
|
|
|
|
2012-10-18 09:19:09 +00:00
|
|
|
|
2012-11-29 06:16:08 +00:00
|
|
|
class FreeVars a where
|
|
|
|
freeVars :: a -> [X]
|
2012-10-18 09:19:09 +00:00
|
|
|
|
2012-11-29 06:16:08 +00:00
|
|
|
instance FreeVars Type where
|
|
|
|
freeVars (VarT v) = [v]
|
|
|
|
freeVars (LambdaT t1 t2) = freeVars t1 ++ freeVars t2
|
|
|
|
freeVars (ADT _ ts) = concatMap freeVars ts
|
2012-12-25 08:39:18 +00:00
|
|
|
freeVars (RecordT fs t) =
|
|
|
|
freeVars (concat $ Map.elems fs) ++ freeVars t
|
|
|
|
freeVars EmptyRecord = []
|
2012-11-29 06:16:08 +00:00
|
|
|
freeVars (Super _ ) = []
|
2012-10-18 09:19:09 +00:00
|
|
|
|
2012-11-29 06:16:08 +00:00
|
|
|
instance FreeVars Constraint where
|
|
|
|
freeVars (t1 :=: t2) = freeVars t1 ++ freeVars t2
|
|
|
|
freeVars (t1 :<: t2) = freeVars t1 ++ freeVars t2
|
|
|
|
freeVars (x :<<: Forall xs cs t) = filter (`notElem` xs) frees
|
|
|
|
where frees = concatMap freeVars cs ++ freeVars t
|
2012-10-18 09:19:09 +00:00
|
|
|
|
2012-12-25 08:39:18 +00:00
|
|
|
instance FreeVars a => FreeVars (Context a) where
|
|
|
|
freeVars (C _ _ c) = freeVars c
|
2012-10-18 09:19:09 +00:00
|
|
|
|
2012-12-25 08:39:18 +00:00
|
|
|
instance FreeVars a => FreeVars [a] where
|
|
|
|
freeVars = concatMap freeVars
|
2012-10-18 09:19:09 +00:00
|
|
|
|
2013-01-03 08:28:54 +00:00
|
|
|
occurs x t = x `elem` freeVars t
|
2012-11-29 06:16:08 +00:00
|
|
|
|
2012-12-25 08:39:18 +00:00
|
|
|
concretize :: Scheme -> GuidCounter (Type, [Context Constraint])
|
2012-11-29 06:16:08 +00:00
|
|
|
concretize (Forall xs cs t) = do
|
|
|
|
ss <- zip xs `liftM` mapM (\_ -> liftM VarT guid) xs
|
|
|
|
return (subst ss t, subst ss cs)
|
|
|
|
|
|
|
|
rescheme :: Scheme -> GuidCounter Scheme
|
|
|
|
rescheme (Forall xs cs t) = do
|
|
|
|
xs' <- mapM (const guid) xs
|
|
|
|
let ss = zip xs (map VarT xs')
|
|
|
|
return $ Forall xs' (subst ss cs) (subst ss t)
|
2012-08-09 14:38:18 +00:00
|
|
|
|
|
|
|
generalize :: [X] -> Scheme -> GuidCounter Scheme
|
|
|
|
generalize exceptions (Forall xs cs t) = rescheme (Forall (xs ++ frees) cs t)
|
2012-11-29 06:16:08 +00:00
|
|
|
where allFrees = Set.fromList $ freeVars t ++ concatMap freeVars cs
|
2012-08-09 14:38:18 +00:00
|
|
|
frees = Set.toList $ Set.difference allFrees (Set.fromList exceptions)
|