git.iko.soy/rowtype-yoga/purescript-native
on d5b3d0d help sign in
309 lines 10 kB history raw
1-----------------------------------------------------------------------------
2--
3-- Module : Language.PureScript.Types
4-- Copyright : (c) Phil Freeman 2013
5-- License : MIT
6--
7-- Maintainer : Phil Freeman <paf31@cantab.net>
8-- Stability : experimental
9-- Portability :
10--
11-- |
12-- Data types for types
13--
14-----------------------------------------------------------------------------
16{-# LANGUAGE DeriveDataTypeable #-}
18module Language.PureScript.Types where
20import Data.Data
21import Data.List (nub)
23import Control.Monad.Unify
24import Control.Arrow (second)
25import Control.Applicative
26import Control.Monad ((<=<))
28import Language.PureScript.Names
29import Language.PureScript.Kinds
30import Language.PureScript.Traversals
32-- |
33-- An identifier for the scope of a skolem variable
34--
35newtype SkolemScope = SkolemScope { runSkolemScope :: Int } deriving (Show, Eq, Ord, Data, Typeable)
37-- |
38-- The type of types
39--
40data Type
41 -- |
42 -- A unification variable of type Type
43 --
44 = TUnknown Unknown
45 -- |
46 -- A named type variable
47 --
48 | TypeVar String
49 -- |
50 -- A type wildcard, as would appear in a partial type synonym
51 --
52 | TypeWildcard
53 -- |
54 -- A type constructor
55 --
56 | TypeConstructor (Qualified ProperName)
57 -- |
58 -- A type application
59 --
60 | TypeApp Type Type
61 -- |
62 -- A type synonym which is \"saturated\", i.e. fully applied
63 --
64 | SaturatedTypeSynonym (Qualified ProperName) [Type]
65 -- |
66 -- Forall quantifier
67 --
68 | ForAll String Type (Maybe SkolemScope)
69 -- |
70 -- A type with a set of type class constraints
71 --
72 | ConstrainedType [(Qualified ProperName, [Type])] Type
73 -- |
74 -- A skolem constant
75 --
76 | Skolem String Int SkolemScope
77 -- |
78 -- An empty row
79 --
80 | REmpty
81 -- |
82 -- A non-empty row
83 --
84 | RCons String Type Type
85 -- |
86 -- A type with a kind annotation
87 --
88 | KindedType Type Kind
89 --
90 -- |
91 -- A placeholder used in pretty printing
92 --
93 | PrettyPrintFunction Type Type
94 -- |
95 -- A placeholder used in pretty printing
96 --
97 | PrettyPrintArray Type
98 -- |
99 -- A placeholder used in pretty printing
100 --
101 | PrettyPrintObject Type
102 -- |
103 -- A placeholder used in pretty printing
104 --
105 | PrettyPrintForAll [String] Type deriving (Show, Eq, Data, Typeable)
107-- |
108-- Convert a row to a list of pairs of labels and types
109--
110rowToList :: Type -> ([(String, Type)], Type)
111rowToList (RCons name ty row) = let (tys, rest) = rowToList row
112 in ((name, ty):tys, rest)
113rowToList r = ([], r)
115-- |
116-- Convert a list of labels and types to a row
117--
118rowFromList :: ([(String, Type)], Type) -> Type
119rowFromList ([], r) = r
120rowFromList ((name, t):ts, r) = RCons name t (rowFromList (ts, r))
122-- |
123-- Check whether a type is a monotype
124--
125isMonoType :: Type -> Bool
126isMonoType ForAll{} = False
127isMonoType _ = True
129-- |
130-- Universally quantify a type
131--
132mkForAll :: [String] -> Type -> Type
133mkForAll args ty = foldl (\t arg -> ForAll arg t Nothing) ty args
135-- |
136-- Replace a type variable, taking into account variable shadowing
137--
138replaceTypeVars :: String -> Type -> Type -> Type
139replaceTypeVars v r = replaceAllTypeVars [(v, r)]
141-- |
142-- Replace named type variables with types
143--
144replaceAllTypeVars :: [(String, Type)] -> Type -> Type
145replaceAllTypeVars = go []
146 where
148 go :: [String] -> [(String, Type)] -> Type -> Type
149 go _ m (TypeVar v) =
150 case v `lookup` m of
151 Just r -> r
152 Nothing -> TypeVar v
153 go bs m (TypeApp t1 t2) = TypeApp (go bs m t1) (go bs m t2)
154 go bs m (SaturatedTypeSynonym name' ts) = SaturatedTypeSynonym name' $ map (go bs m) ts
155 go bs m f@(ForAll v t sco) | v `elem` keys = go bs (filter ((/= v) . fst) m) f
156 | v `elem` usedVars =
157 let v' = genName v (keys ++ bs ++ usedVars)
158 t' = go bs [(v, TypeVar v')] t
159 in ForAll v' (go (v' : bs) m t') sco
160 | otherwise = ForAll v (go (v : bs) m t) sco
161 where
162 keys = map fst m
163 usedVars = concatMap (usedTypeVariables . snd) m
164 go bs m (ConstrainedType cs t) = ConstrainedType (map (second $ map (go bs m)) cs) (go bs m t)
165 go bs m (RCons name' t r) = RCons name' (go bs m t) (go bs m r)
166 go bs m (KindedType t k) = KindedType (go bs m t) k
167 go _ _ ty = ty
169 genName orig inUse = try 0
170 where
171 try :: Integer -> String
172 try n | (orig ++ show n) `elem` inUse = try (n + 1)
173 | otherwise = orig ++ show n
175-- |
176-- Collect all type variables appearing in a type
177--
178usedTypeVariables :: Type -> [String]
179usedTypeVariables = nub . everythingOnTypes (++) go
180 where
181 go (TypeVar v) = [v]
182 go _ = []
184-- |
185-- Collect all free type variables appearing in a type
186--
187freeTypeVariables :: Type -> [String]
188freeTypeVariables = nub . go []
189 where
190 go :: [String] -> Type -> [String]
191 go bound (TypeVar v) | v `notElem` bound = [v]
192 go bound (TypeApp t1 t2) = go bound t1 ++ go bound t2
193 go bound (SaturatedTypeSynonym _ ts) = concatMap (go bound) ts
194 go bound (ForAll v t _) = go (v : bound) t
195 go bound (ConstrainedType cs t) = concatMap (concatMap (go bound) . snd) cs ++ go bound t
196 go bound (RCons _ t r) = go bound t ++ go bound r
197 go bound (KindedType t _) = go bound t
198 go _ _ = []
200-- |
201-- Universally quantify over all type variables appearing free in a type
202--
203quantify :: Type -> Type
204quantify ty = foldr (\arg t -> ForAll arg t Nothing) ty $ freeTypeVariables ty
206-- |
207-- Move all universal quantifiers to the front of a type
208--
209moveQuantifiersToFront :: Type -> Type
210moveQuantifiersToFront = go [] []
211 where
212 go qs cs (ForAll q ty sco) = go ((q, sco) : qs) cs ty
213 go qs cs (ConstrainedType cs' ty) = go qs (cs ++ cs') ty
214 go qs cs ty =
215 let constrained = case cs of
216 [] -> ty
217 cs' -> ConstrainedType cs' ty
218 in case qs of
219 [] -> constrained
220 qs' -> foldl (\ty' (q, sco) -> ForAll q ty' sco) constrained qs'
222-- |
223-- Check if a type contains wildcards
224--
225containsWildcards :: Type -> Bool
226containsWildcards = everythingOnTypes (||) go
227 where
228 go :: Type -> Bool
229 go TypeWildcard = True
230 go _ = False
232--
233-- Traversals
234--
236everywhereOnTypes :: (Type -> Type) -> Type -> Type
237everywhereOnTypes f = go
238 where
239 go (TypeApp t1 t2) = f (TypeApp (go t1) (go t2))
240 go (SaturatedTypeSynonym name tys) = f (SaturatedTypeSynonym name (map go tys))
241 go (ForAll arg ty sco) = f (ForAll arg (go ty) sco)
242 go (ConstrainedType cs ty) = f (ConstrainedType (map (fmap (map go)) cs) (go ty))
243 go (RCons name ty rest) = f (RCons name (go ty) (go rest))
244 go (KindedType ty k) = f (KindedType (go ty) k)
245 go (PrettyPrintFunction t1 t2) = f (PrettyPrintFunction (go t1) (go t2))
246 go (PrettyPrintArray t) = f (PrettyPrintArray (go t))
247 go (PrettyPrintObject t) = f (PrettyPrintObject (go t))
248 go (PrettyPrintForAll args t) = f (PrettyPrintForAll args (go t))
249 go other = f other
251everywhereOnTypesTopDown :: (Type -> Type) -> Type -> Type
252everywhereOnTypesTopDown f = go . f
253 where
254 go (TypeApp t1 t2) = TypeApp (go (f t1)) (go (f t2))
255 go (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym name (map (go . f) tys)
256 go (ForAll arg ty sco) = ForAll arg (go (f ty)) sco
257 go (ConstrainedType cs ty) = ConstrainedType (map (fmap (map (go . f))) cs) (go (f ty))
258 go (RCons name ty rest) = RCons name (go (f ty)) (go (f rest))
259 go (KindedType ty k) = KindedType (go (f ty)) k
260 go (PrettyPrintFunction t1 t2) = PrettyPrintFunction (go (f t1)) (go (f t2))
261 go (PrettyPrintArray t) = PrettyPrintArray (go (f t))
262 go (PrettyPrintObject t) = PrettyPrintObject (go (f t))
263 go (PrettyPrintForAll args t) = PrettyPrintForAll args (go (f t))
264 go other = f other
266everywhereOnTypesM :: (Functor m, Applicative m, Monad m) => (Type -> m Type) -> Type -> m Type
267everywhereOnTypesM f = go
268 where
269 go (TypeApp t1 t2) = (TypeApp <$> go t1 <*> go t2) >>= f
270 go (SaturatedTypeSynonym name tys) = (SaturatedTypeSynonym name <$> mapM go tys) >>= f
271 go (ForAll arg ty sco) = (ForAll arg <$> go ty <*> pure sco) >>= f
272 go (ConstrainedType cs ty) = (ConstrainedType <$> mapM (sndM (mapM go)) cs <*> go ty) >>= f
273 go (RCons name ty rest) = (RCons name <$> go ty <*> go rest) >>= f
274 go (KindedType ty k) = (KindedType <$> go ty <*> pure k) >>= f
275 go (PrettyPrintFunction t1 t2) = (PrettyPrintFunction <$> go t1 <*> go t2) >>= f
276 go (PrettyPrintArray t) = (PrettyPrintArray <$> go t) >>= f
277 go (PrettyPrintObject t) = (PrettyPrintObject <$> go t) >>= f
278 go (PrettyPrintForAll args t) = (PrettyPrintForAll args <$> go t) >>= f
279 go other = f other
281everywhereOnTypesTopDownM :: (Functor m, Applicative m, Monad m) => (Type -> m Type) -> Type -> m Type
282everywhereOnTypesTopDownM f = go <=< f
283 where
284 go (TypeApp t1 t2) = TypeApp <$> (f t1 >>= go) <*> (f t2 >>= go)
285 go (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym name <$> mapM (go <=< f) tys
286 go (ForAll arg ty sco) = ForAll arg <$> (f ty >>= go) <*> pure sco
287 go (ConstrainedType cs ty) = ConstrainedType <$> mapM (sndM (mapM (go <=< f))) cs <*> (f ty >>= go)
288 go (RCons name ty rest) = RCons name <$> (f ty >>= go) <*> (f rest >>= go)
289 go (KindedType ty k) = KindedType <$> (f ty >>= go) <*> pure k
290 go (PrettyPrintFunction t1 t2) = PrettyPrintFunction <$> (f t1 >>= go) <*> (f t2 >>= go)
291 go (PrettyPrintArray t) = PrettyPrintArray <$> (f t >>= go)
292 go (PrettyPrintObject t) = PrettyPrintObject <$> (f t >>= go)
293 go (PrettyPrintForAll args t) = PrettyPrintForAll args <$> (f t >>= go)
294 go other = f other
296everythingOnTypes :: (r -> r -> r) -> (Type -> r) -> Type -> r
297everythingOnTypes (<>) f = go
298 where
299 go t@(TypeApp t1 t2) = f t <> go t1 <> go t2
300 go t@(SaturatedTypeSynonym _ tys) = foldl (<>) (f t) (map go tys)
301 go t@(ForAll _ ty _) = f t <> go ty
302 go t@(ConstrainedType cs ty) = foldl (<>) (f t) (map go $ concatMap snd cs) <> go ty
303 go t@(RCons _ ty rest) = f t <> go ty <> go rest
304 go t@(KindedType ty _) = f t <> go ty
305 go t@(PrettyPrintFunction t1 t2) = f t <> go t1 <> go t2
306 go t@(PrettyPrintArray t1) = f t <> go t1
307 go t@(PrettyPrintObject t1) = f t <> go t1
308 go t@(PrettyPrintForAll _ t1) = f t <> go t1
309 go other = f other