@@ -18,9 +18,11 @@
18module Language.PureScript.Types where
18module Language.PureScript.Types where
20import Data.Data
20import Data.Data
21+import Data.List (nub)
21−import Data.Generics (mkT, mkQ, everywhereBut)
22+import Data.Generics (everything, mkT, mkQ, everywhereBut)
23import Control.Monad.Unify
24import Control.Monad.Unify
25+import Control.Arrow ((***))
25import Language.PureScript.Names
27import Language.PureScript.Names
@@ -159,24 +161,49 @@ unit = Object REmpty
160-- Replace a type variable, taking into account variable shadowing
162-- Replace a type variable, taking into account variable shadowing
162−replaceTypeVars :: (Data d) => String -> Type -> d -> d
164+replaceTypeVars :: String -> Type -> Type -> Type
163−replaceTypeVars name t = everywhereBut (mkQ False isShadowed) (mkT replaceTypeVar)
165+replaceTypeVars = replaceTypeVars' []
167+ replaceTypeVars' bound name replacement = go bound
169+ go :: [String] -> Type -> Type
170+ go bs (Object r) = Object $ go bs r
165− replaceTypeVar (TypeVar v) | v == name = t
171+ go bs (TypeVar v) | v == name = replacement
166− replaceTypeVar other = other
172+ go bs (TypeApp t1 t2) = TypeApp (go bs t1) (go bs t2)
173+ go bs (SaturatedTypeSynonym name ts) = SaturatedTypeSynonym name $ map (go bs) ts
167− isShadowed (ForAll v _ _) | v == name = True
174+ go bs f@(ForAll v t sco) | v == name = f
168− isShadowed _ = False
175+ | v `elem` usedTypeVariables replacement =
176+ let v' = genName v (name : bs ++ usedTypeVariables replacement)
177+ t' = replaceTypeVars' bs v (TypeVar v') t
178+ in ForAll v' (go (v' : bs) t') sco
179+ | otherwise = ForAll v (go (v : bs) t) sco
180+ go bs (ConstrainedType cs t) = ConstrainedType (map (id *** go bs) cs) (go bs t)
181+ go bs (RCons name t r) = RCons name (go bs t) (go bs r)
183+ genName orig inUse = try 0
185+ try n | (orig ++ show n) `elem` inUse = try (n + 1)
186+ | otherwise = orig ++ show n
189+-- Collect all type variables appearing in a type
191+usedTypeVariables :: Type -> [String]
192+usedTypeVariables = nub . everything (++) (mkQ [] go)
194+ go (TypeVar v) = [v]
171-- Collect all free type variables appearing in a type
198-- Collect all free type variables appearing in a type
173freeTypeVariables :: Type -> [String]
200freeTypeVariables :: Type -> [String]
174−freeTypeVariables = go []
201+freeTypeVariables = nub . go []
176 go :: [String] -> Type -> [String]
203 go :: [String] -> Type -> [String]
177 go bound (Object r) = go bound r
204 go bound (Object r) = go bound r
178 go bound (TypeVar v) | v `notElem` bound = [v]
205 go bound (TypeVar v) | v `notElem` bound = [v]
179− go bound (TypeApp t1 t2) = go bound t1 ++ go bound t2
206+ go bound (TypeApp t1 t2) = go bound t1 ++ go bound t2
180 go bound (SaturatedTypeSynonym _ ts) = concatMap (go bound) ts
207 go bound (SaturatedTypeSynonym _ ts) = concatMap (go bound) ts
181 go bound (ForAll v t _) = go (v : bound) t
208 go bound (ForAll v t _) = go (v : bound) t
182 go bound (ConstrainedType cs t) = concatMap (go bound . snd) cs ++ go bound t
209 go bound (ConstrainedType cs t) = concatMap (go bound . snd) cs ++ go bound t