@@ -18,9 +18,11 @@
1818module Language.PureScript.Types where
1919
2020import Data.Data
21−import Data.Generics (mkT, mkQ, everywhereBut)
21+import Data.List (nub)
22+import Data.Generics (everything, mkT, mkQ, everywhereBut)
2223
2324import Control.Monad.Unify
25+import Control.Arrow ((***))
2426
2527import Language.PureScript.Names
2628
@@ -159,24 +161,49 @@ unit = Object REmpty
159161-- |
160162-- Replace a type variable, taking into account variable shadowing
161163--
162−replaceTypeVars :: (Data d) => String -> Type -> d -> d
163−replaceTypeVars name t = everywhereBut (mkQ False isShadowed) (mkT replaceTypeVar)
164+replaceTypeVars :: String -> Type -> Type -> Type
165+replaceTypeVars = replaceTypeVars' []
164166 where
165− replaceTypeVar (TypeVar v) | v == name = t
166− replaceTypeVar other = other
167− isShadowed (ForAll v _ _) | v == name = True
168− isShadowed _ = False
167+ replaceTypeVars' bound name replacement = go bound
168+ where
169+ go :: [String] -> Type -> Type
170+ go bs (Object r) = Object $ go bs r
171+ go bs (TypeVar v) | v == name = replacement
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
174+ go bs f@(ForAll v t sco) | v == name = f
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)
182+ go _ ty = ty
183+ genName orig inUse = try 0
184+ where
185+ try n | (orig ++ show n) `elem` inUse = try (n + 1)
186+ | otherwise = orig ++ show n
187+
188+-- |
189+-- Collect all type variables appearing in a type
190+--
191+usedTypeVariables :: Type -> [String]
192+usedTypeVariables = nub . everything (++) (mkQ [] go)
193+ where
194+ go (TypeVar v) = [v]
195+ go _ = []
169196
170197-- |
171198-- Collect all free type variables appearing in a type
172199--
173200freeTypeVariables :: Type -> [String]
174−freeTypeVariables = go []
201+freeTypeVariables = nub . go []
175202 where
176203 go :: [String] -> Type -> [String]
177204 go bound (Object r) = go bound r
178205 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
180207 go bound (SaturatedTypeSynonym _ ts) = concatMap (go bound) ts
181208 go bound (ForAll v t _) = go (v : bound) t
182209 go bound (ConstrainedType cs t) = concatMap (go bound . snd) cs ++ go bound t