1-----------------------------------------------------------------------------
3-- Module : PureScript.TypeChecker.Kinds
4-- Copyright : (c) Phil Freeman 2013
7-- Maintainer : Phil Freeman <paf31@cantab.net>
8-- Stability : experimental
13-----------------------------------------------------------------------------
15{-# LANGUAGE DeriveDataTypeable #-}
17module PureScript.TypeChecker.Kinds (
25import Data.Maybe (fromMaybe)
29import PureScript.Types
30import PureScript.Kinds
31import PureScript.Declarations
32import PureScript.TypeChecker.Monad
33import PureScript.CodeGen.Pretty.Kinds
34import PureScript.CodeGen.Pretty.Types
36import Control.Monad.State
37import Control.Monad.Error
39import Control.Applicative
40import Control.Arrow (Kleisli(..), (***))
41import qualified Control.Category as C
43import qualified Data.Map as M
45data KindConstraintOrigin
48 | RowOrigin Row deriving (Show, Data, Typeable)
50prettyPrintKindConstraintOrigin :: KindConstraintOrigin -> String
51prettyPrintKindConstraintOrigin (DataDeclOrigin) = "data declaration"
52prettyPrintKindConstraintOrigin (TypeOrigin ty) = prettyPrintType ty
53prettyPrintKindConstraintOrigin (RowOrigin row) = prettyPrintRow row
55data KindConstraint = KindConstraint Int Kind KindConstraintOrigin deriving (Show, Data, Typeable)
57newtype KindSolution = KindSolution { runKindSolution :: Int -> Kind }
59emptyKindSolution :: KindSolution
60emptyKindSolution = KindSolution KUnknown
62kindOf :: PolyType -> Check Kind
63kindOf (PolyType idents ty) = do
64 ns <- replicateM (length idents) fresh
65 (cs, n, m) <- kindConstraints (M.fromList (zip idents ns)) ty
66 solution <- solveKindConstraints cs emptyKindSolution
67 return $ starIfUnknown $ runKindSolution solution n
69kindsOf :: Maybe String -> [String] -> [Type] -> Check Kind
70kindsOf name args ts = do
72 nargs <- replicateM (length args) fresh
73 (cs, ns, m) <- kindConstraintsAll (maybe id (flip M.insert tyCon) name $ M.fromList (zipWith (,) args nargs)) ts
74 let extraConstraints =
75 KindConstraint tyCon (foldr FunKind Star (map KUnknown nargs)) DataDeclOrigin
76 : zipWith (\n arg -> KindConstraint n Star (TypeOrigin arg)) ns ts
77 solution <- solveKindConstraints (extraConstraints ++ cs) emptyKindSolution
78 return $ starIfUnknown $ runKindSolution solution tyCon
80starIfUnknown :: Kind -> Kind
81starIfUnknown (KUnknown _) = Star
82starIfUnknown (FunKind k1 k2) = FunKind (starIfUnknown k1) (starIfUnknown k2)
85kindConstraintsAll :: M.Map String Int -> [Type] -> Check ([KindConstraint], [Int], M.Map String Int)
86kindConstraintsAll m [] = return ([], [], m)
87kindConstraintsAll m (t:ts) = do
88 (cs, n1, m') <- kindConstraints m t
89 (cs', ns, m'') <- kindConstraintsAll m' ts
90 return ((KindConstraint n1 Star (TypeOrigin t)) : cs ++ cs', n1:ns, m'')
92kindConstraints :: M.Map String Int -> Type -> Check ([KindConstraint], Int, M.Map String Int)
93kindConstraints m a@(Array t) = do
95 (cs, n1, m') <- kindConstraints m t
96 return ((KindConstraint n1 Star (TypeOrigin t)) : (KindConstraint me Star (TypeOrigin a)) : cs, me, m')
97kindConstraints m o@(Object row) = do
99 (cs, r, m') <- kindConstraintsForRow m row
100 return ((KindConstraint me Star (TypeOrigin o)) : (KindConstraint r Row (RowOrigin row)) : cs, me, m')
101kindConstraints m f@(Function args ret) = do
103 (cs, ns, m') <- kindConstraintsAll m args
104 (cs', retN, m'') <- kindConstraints m' ret
105 return ((KindConstraint retN Star (TypeOrigin ret)) : (KindConstraint me Star (TypeOrigin f)) : (zipWith (\n arg -> KindConstraint n Star (TypeOrigin arg)) ns args) ++ cs ++ cs', me, m'')
106kindConstraints m (TypeVar v) = do
108 Just u -> return ([], u, m)
109 Nothing -> throwError $ "Unbound type variable " ++ v
110kindConstraints m c@(TypeConstructor v) = do
114 Nothing -> case M.lookup v (types env) of
115 Nothing -> throwError $ "Unknown type constructor '" ++ v ++ "'"
116 Just (kind, _) -> return ([KindConstraint me kind (TypeOrigin c)], me, m)
118 return ([KindConstraint me (KUnknown u) (TypeOrigin c)], me, m)
119kindConstraints m a@(TypeApp t1 t2) = do
121 (cs1, n1, m1) <- kindConstraints m t1
122 (cs2, n2, m2) <- kindConstraints m1 t2
123 return ((KindConstraint n1 (FunKind (KUnknown n2) (KUnknown me)) (TypeOrigin a)) : cs1 ++ cs2, me, m2)
124kindConstraints m t = do
126 return ([KindConstraint me Star (TypeOrigin t)], me, m)
128kindConstraintsForRow :: M.Map String Int -> Row -> Check ([KindConstraint], Int, M.Map String Int)
129kindConstraintsForRow m r@(RowVar v) = do
130 me <- case M.lookup v m of
133 return ([KindConstraint me Row (RowOrigin r)], me, M.insert v me m)
134kindConstraintsForRow m r@REmpty = do
136 return ([KindConstraint me Row (RowOrigin r)], me, m)
137kindConstraintsForRow m r@(RCons _ ty row) = do
139 (cs1, n1, m1) <- kindConstraints m ty
140 (cs2, n2, m2) <- kindConstraintsForRow m1 row
141 return ((KindConstraint me Row (RowOrigin r)) : (KindConstraint n1 Star (TypeOrigin ty)) : (KindConstraint n2 Row (RowOrigin r)) : cs1 ++ cs2, me, m2)
143solveKindConstraints :: [KindConstraint] -> KindSolution -> Check KindSolution
144solveKindConstraints [] s = return s
145solveKindConstraints all@(KindConstraint n k t : cs) s = do
146 (cs', s') <- rethrow (\err -> "Error in " ++ prettyPrintKindConstraintOrigin t ++ ": " ++ err) $ do
147 guardWith "Occurs check failed" $ not $ kindOccursCheck False n k
148 let s' = KindSolution $ replaceUnknownKind n k . runKindSolution s
149 cs' <- fmap concat $ mapM (substituteKindConstraint n k) cs
151 solveKindConstraints cs' s'
153substituteKindConstraint :: Int -> Kind -> KindConstraint -> Check [KindConstraint]
154substituteKindConstraint n k (KindConstraint m l t)
155 | n == m = unifyKinds t k l
156 | otherwise = return [KindConstraint m (replaceUnknownKind n k l) t]
158replaceUnknownKind :: Int -> Kind -> Kind -> Kind
159replaceUnknownKind n k = f
161 f (KUnknown m) | m == n = k
162 f (FunKind k1 k2) = FunKind (f k2) (f k2)
165unifyKinds :: KindConstraintOrigin -> Kind -> Kind -> Check [KindConstraint]
166unifyKinds _ (KUnknown u1) (KUnknown u2) | u1 == u2 = return []
167unifyKinds t (KUnknown u) k = do
168 guardWith "Occurs check failed" $ not $ kindOccursCheck False u k
169 return [KindConstraint u k t]
170unifyKinds t k (KUnknown u) = do
171 guardWith "Occurs check failed" $ not $ kindOccursCheck False u k
172 return [KindConstraint u k t]
173unifyKinds _ Star Star = return []
174unifyKinds _ Row Row = return []
175unifyKinds t (FunKind k1 k2) (FunKind k3 k4) = do
176 cs1 <- unifyKinds t k1 k3
177 cs2 <- unifyKinds t k2 k4
179unifyKinds _ k1 k2 = throwError $ "Cannot unify " ++ prettyPrintKind k1 ++ " with " ++ prettyPrintKind k2 ++ "."
181kindOccursCheck :: Bool -> Int -> Kind -> Bool
182kindOccursCheck b u (KUnknown u') | u == u' = b
183kindOccursCheck _ u (FunKind k1 k2) = kindOccursCheck True u k1 || kindOccursCheck True u k2
184kindOccursCheck _ _ _ = False
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list