@@ -45,7 +45,8 @@ import Data.List
45import Data.Maybe (maybeToList, isNothing, isJust, fromMaybe)
45import Data.Maybe (maybeToList, isNothing, isJust, fromMaybe)
46import qualified Data.Data as D
46import qualified Data.Data as D
47import Data.Generics
47import Data.Generics
48+ (everythingWithContext, mkM, everywhereM, everything, mkT,
48− (mkM, everywhereM, everything, mkT, something, everywhere, mkQ)
49+ something, everywhere, mkQ)
50import Language.PureScript.Values
51import Language.PureScript.Values
51import Language.PureScript.Types
52import Language.PureScript.Types
@@ -66,6 +67,7 @@ import Control.Arrow (Arrow(..))
67import qualified Data.Map as M
68import qualified Data.Map as M
68import Data.Function (on)
69import Data.Function (on)
70+import Debug.Trace (trace)
70instance Partial Type where
72instance Partial Type where
71 unknown = TUnknown
73 unknown = TUnknown
@@ -86,17 +88,23 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
86 unifyTypes' (TUnknown u) t = u =:= t
88 unifyTypes' (TUnknown u) t = u =:= t
87 unifyTypes' t (TUnknown u) = u =:= t
89 unifyTypes' t (TUnknown u) = u =:= t
88 unifyTypes' (SaturatedTypeSynonym name args) ty = do
90 unifyTypes' (SaturatedTypeSynonym name args) ty = do
89− ty1 <- expandTypeSynonym name args
91+ ty1 <- introduceSkolemScope <=< expandTypeSynonym name $ args
90 ty1 `unifyTypes` ty
92 ty1 `unifyTypes` ty
91 unifyTypes' ty s@(SaturatedTypeSynonym _ _) = s `unifyTypes` ty
93 unifyTypes' ty s@(SaturatedTypeSynonym _ _) = s `unifyTypes` ty
92− unifyTypes' (ForAll ident1 ty1) (ForAll ident2 ty2) = do
94+ unifyTypes' (ForAll ident1 ty1 sc1) (ForAll ident2 ty2 sc2) =
96+ (Just sc1', Just sc2') -> do
97+ sko <- newSkolemConstant
93− sk <- skolemize ident1 ty1
98+ let sk1 = skolemize ident1 sko sc1' ty1
94− replaced <- replaceVarWithUnknown ident2 ty2
99+ let sk2 = skolemize ident2 sko sc2' ty2
95− sk `unifyTypes` replaced
100+ sk1 `unifyTypes` sk2
101+ _ -> throwError (prettyPrintType ty1)
96− unifyTypes' (ForAll ident ty1) ty2 = do
102+ unifyTypes' (ForAll ident ty1 (Just sc)) ty2 = do
103+ sko <- newSkolemConstant
97− sk <- skolemize ident ty1
104+ let sk = skolemize ident sko sc ty1
98 sk `unifyTypes` ty2
105 sk `unifyTypes` ty2
106+ unifyTypes' (ForAll _ _ _) _ = throwError "Skolem variable scope is unspecified"
99− unifyTypes' ty f@(ForAll _ _) = f `unifyTypes` ty
107+ unifyTypes' ty f@(ForAll _ _ _) = f `unifyTypes` ty
100 unifyTypes' (Object row1) (Object row2) = row1 =?= row2
108 unifyTypes' (Object row1) (Object row2) = row1 =?= row2
101 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
109 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
102 unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do
110 unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do
@@ -106,7 +114,7 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
106 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
114 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
107 t3 `unifyTypes` t5
115 t3 `unifyTypes` t5
108 t4 `unifyTypes` t6
116 t4 `unifyTypes` t6
109− unifyTypes' (Skolem s1) (Skolem s2) | s1 == s2 = return ()
117+ unifyTypes' (Skolem s1 _) (Skolem s2 _) | s1 == s2 = return ()
110 unifyTypes' r1@(RCons _ _ _) r2 = unifyRows r1 r2
118 unifyTypes' r1@(RCons _ _ _) r2 = unifyRows r1 r2
111 unifyTypes' r1 r2@(RCons _ _ _) = unifyRows r1 r2
119 unifyTypes' r1 r2@(RCons _ _ _) = unifyRows r1 r2
112 unifyTypes' r1@REmpty r2 = unifyRows r1 r2
120 unifyTypes' r1@REmpty r2 = unifyRows r1 r2
@@ -143,7 +151,7 @@ unifyRows r1 r2 =
143 unifyRows' row r others u'
151 unifyRows' row r others u'
144 unifyRows' [] REmpty [] REmpty = return ()
152 unifyRows' [] REmpty [] REmpty = return ()
145 unifyRows' [] (TypeVar v1) [] (TypeVar v2) | v1 == v2 = return ()
153 unifyRows' [] (TypeVar v1) [] (TypeVar v2) | v1 == v2 = return ()
146− unifyRows' [] (Skolem s1) [] (Skolem s2) | s1 == s2 = return ()
154+ unifyRows' [] (Skolem s1 _) [] (Skolem s2 _) | s1 == s2 = return ()
147 unifyRows' sd3 r3 sd4 r4 = throwError $ "Cannot unify " ++ prettyPrintRow (rowFromList (sd3, r3)) ++ " with " ++ prettyPrintRow (rowFromList (sd4, r4)) ++ "."
155 unifyRows' sd3 r3 sd4 r4 = throwError $ "Cannot unify " ++ prettyPrintRow (rowFromList (sd3, r3)) ++ " with " ++ prettyPrintRow (rowFromList (sd4, r4)) ++ "."
@@ -171,22 +179,24 @@ typesOf moduleName vals = do
171 (ident, (val, Just (ty, checkType))) -> do
179 (ident, (val, Just (ty, checkType))) -> do
172 kind <- liftCheck $ kindOf moduleName ty
180 kind <- liftCheck $ kindOf moduleName ty
173 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
181 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
174− ty' <- replaceAllTypeSynonyms ty
182+ ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
175− val' <- bindNames dict $ if checkType then check val ty' else return val
183+ val' <- bindNames dict $ if checkType
184+ then TypedValue True <$> check val ty' <*> pure ty'
185+ else return (TypedValue False val ty')
176 return (ident, (val', ty'))
186 return (ident, (val', ty'))
177 (ident, (val, Nothing)) -> do
187 (ident, (val, Nothing)) -> do
178 TypedValue _ val' ty <- bindNames dict $ infer val
188 TypedValue _ val' ty <- bindNames dict $ infer val
179 ty =?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
189 ty =?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
180− return (ident, (val', ty))
190+ return (ident, (TypedValue True val' ty, ty))
181 when (moduleName == ModuleName (ProperName "Main") && fst e == Ident "main") $ do
191 when (moduleName == ModuleName (ProperName "Main") && fst e == Ident "main") $ do
182 [eff, a] <- replicateM 2 fresh
192 [eff, a] <- replicateM 2 fresh
183 ty =?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName (ProperName "Eff"))) (ProperName "Eff"))) eff) a
193 ty =?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName (ProperName "Eff"))) (ProperName "Eff"))) eff) a
184 escapeCheck val ty
194 escapeCheck val ty
185 return triple
195 return triple
186− forM_ tys $ skolemEscapeCheck . snd . snd
187 forM tys $ \(ident, (val, ty)) -> do
196 forM tys $ \(ident, (val, ty)) -> do
188 val' <- replaceTypeClassDictionaries moduleName val
197 val' <- replaceTypeClassDictionaries moduleName val
198+ rethrow (("Error in " ++ show ident ++ ": \n") ++) $ skolemEscapeCheck val'
189− return (ident, (overTypes (desaturateAllTypeSynonyms . setifyAll) $ val'
199+ return $ (ident, (overTypes (desaturateAllTypeSynonyms . setifyAll) $ val'
190 , varIfUnknown . desaturateAllTypeSynonyms . setifyAll $ ty))
200 , varIfUnknown . desaturateAllTypeSynonyms . setifyAll $ ty))
192 tidyUp (ts, sub) = map (\(i, (val, ty)) -> (i, (overTypes (sub $?) val, sub $? ty))) ts
202 tidyUp (ts, sub) = map (\(i, (val, ty)) -> (i, (overTypes (sub $?) val, sub $? ty))) ts
@@ -238,7 +248,7 @@ entails moduleName context goal@(className, ty) = do
238 return $ Just dict
248 return $ Just dict
239 mkDictionary :: Qualified Ident -> Maybe [Value] -> Value
249 mkDictionary :: Qualified Ident -> Maybe [Value] -> Value
240 mkDictionary fnName Nothing = Var fnName
250 mkDictionary fnName Nothing = Var fnName
241− mkDictionary fnName (Just dicts) = foldr (flip App) (Var fnName) dicts
251+ mkDictionary fnName (Just dicts) = foldl App (Var fnName) dicts
242 filterModule :: TypeClassDictionaryInScope -> Bool
252 filterModule :: TypeClassDictionaryInScope -> Bool
243 filterModule (TypeClassDictionaryInScope { tcdName = Qualified (Just mn) _ }) | mn == moduleName = True
253 filterModule (TypeClassDictionaryInScope { tcdName = Qualified (Just mn) _ }) | mn == moduleName = True
244 filterModule (TypeClassDictionaryInScope { tcdName = Qualified Nothing _ }) = True
254 filterModule (TypeClassDictionaryInScope { tcdName = Qualified Nothing _ }) = True
@@ -252,7 +262,9 @@ entails moduleName context goal@(className, ty) = do
252-- and return a substitution from type variables to types which makes the type heads unify.
262-- and return a substitution from type variables to types which makes the type heads unify.
254typeHeadsAreEqual :: ModuleName -> Environment -> Type -> Type -> Maybe [(String, Type)]
264typeHeadsAreEqual :: ModuleName -> Environment -> Type -> Type -> Maybe [(String, Type)]
255−typeHeadsAreEqual _ _ (Skolem s1) (Skolem s2) | s1 == s2 = Just []
265+typeHeadsAreEqual _ _ (Skolem s1 _) (Skolem s2 _) | s1 == s2 = Just []
266+typeHeadsAreEqual _ _ (TypeVar v) t = Just [(v, t)]
267+typeHeadsAreEqual _ _ t (TypeVar v) = Just [(v, t)]
256typeHeadsAreEqual m e (TypeConstructor c1) (TypeConstructor c2) | typeConstructorsAreEqual e m c1 c2 = Just []
268typeHeadsAreEqual m e (TypeConstructor c1) (TypeConstructor c2) | typeConstructorsAreEqual e m c1 c2 = Just []
257typeHeadsAreEqual m e (TypeApp h1 (TypeVar v)) (TypeApp h2 arg) = (:) (v, arg) <$> typeHeadsAreEqual m e h1 h2
269typeHeadsAreEqual m e (TypeApp h1 (TypeVar v)) (TypeApp h2 arg) = (:) (v, arg) <$> typeHeadsAreEqual m e h1 h2
258typeHeadsAreEqual m e t1@(TypeApp _ _) t2@(TypeApp _ (TypeVar _)) = typeHeadsAreEqual m e t2 t1
270typeHeadsAreEqual m e t1@(TypeApp _ _) t2@(TypeApp _ (TypeVar _)) = typeHeadsAreEqual m e t2 t1
@@ -268,7 +280,7 @@ escapeCheck value ty = do
268 let allUnknowns = findAllTypes value
280 let allUnknowns = findAllTypes value
269 forM_ allUnknowns $ \t -> do
281 forM_ allUnknowns $ \t -> do
270 let unsolvedUnknowns = nub . unknowns $ subst $? t
282 let unsolvedUnknowns = nub . unknowns $ subst $? t
271− guardWith ("Escape check fails" ++ show (subst $? ty, subst $? t)) $ null $ unsolvedUnknowns \\ visibleUnknowns
283+ guardWith "Escape check fails" $ null $ unsolvedUnknowns \\ visibleUnknowns
274-- Find all type annotations occuring inside a value
286-- Find all type annotations occuring inside a value
@@ -282,14 +294,31 @@ findAllTypes = everything (++) (mkQ [] go)
283-- Ensure skolem variables do not escape their scope
295-- Ensure skolem variables do not escape their scope
285−skolemEscapeCheck :: Type -> Check ()
297+skolemEscapeCheck :: Value -> Check ()
286−skolemEscapeCheck ty =
298+skolemEscapeCheck (TypedValue False _ _) = return ()
287− case something (mkQ Nothing findSkolems) ty of
299+skolemEscapeCheck root@(TypedValue _ _ _) =
300+ case everythingWithContext [] (++) (mkQ ((,) []) go) root of
288− Nothing -> return ()
301+ [] -> return ()
289− Just _ -> throwError $ "Skolem variables cannot escape. Consider adding a type signature."
302+ ((binding, val) : _) -> throwError $ "Rigid/skolem type variable bound by " ++ maybe "<unknown>" prettyPrintValue binding ++ " has escaped at " ++ prettyPrintValue val
291− findSkolems (Skolem _) = return ()
304+ go :: Value -> [(SkolemScope, Value)] -> ([(Maybe Value, Value)], [(SkolemScope, Value)])
292− findSkolems _ = mzero
305+ go val@(TypedValue _ _ (ForAll _ _ (Just sco))) scos = ([], (sco, val) : scos)
306+ go val@(TypedValue _ _ ty) scos = case collectSkolems ty \\ map fst scos of
307+ (sco : _) -> ([(findBindingScope sco, val)], scos)
310+ collectSkolems :: Type -> [SkolemScope]
311+ collectSkolems = nub . everything (++) (mkQ [] collect)
313+ collect (Skolem _ scope) = [scope]
315+ go _ scos = ([], scos)
316+ findBindingScope :: SkolemScope -> Maybe Value
317+ findBindingScope sco = something (mkQ Nothing go) root
319+ go val@(TypedValue _ _ (ForAll _ _ (Just sco'))) | sco == sco' = Just val
321+skolemEscapeCheck val = throwError $ "Untyped value passed to skolemEscapeCheck: " ++ prettyPrintValue val
295-- Ensure a row contains no duplicate labels
324-- Ensure a row contains no duplicate labels
@@ -326,7 +355,7 @@ replaceAllTypeVars = foldl' (\f (name, ty) -> replaceTypeVars name ty . f) id
326-- Replace named type variables with new unification variables
355-- Replace named type variables with new unification variables
328replaceAllVarsWithUnknowns :: Type -> UnifyT Type Check Type
357replaceAllVarsWithUnknowns :: Type -> UnifyT Type Check Type
329−replaceAllVarsWithUnknowns (ForAll ident ty) = replaceVarWithUnknown ident ty >>= replaceAllVarsWithUnknowns
358+replaceAllVarsWithUnknowns (ForAll ident ty _) = replaceVarWithUnknown ident ty >>= replaceAllVarsWithUnknowns
330replaceAllVarsWithUnknowns ty = return ty
359replaceAllVarsWithUnknowns ty = return ty
@@ -404,7 +433,8 @@ infer' (ObjectUpdate o ps) = do
404 newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> mapM (infer . snd) ps
433 newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> mapM (infer . snd) ps
405 let newTys = map (\(name, TypedValue _ _ ty) -> (name, ty)) newVals
434 let newTys = map (\(name, TypedValue _ _ ty) -> (name, ty)) newVals
406 oldTys <- zip (map fst ps) <$> replicateM (length ps) fresh
435 oldTys <- zip (map fst ps) <$> replicateM (length ps) fresh
407− o' <- check o $ Object $ rowFromList (oldTys, row)
436+ let oldTy = Object $ rowFromList (oldTys, row)
437+ o' <- TypedValue True <$> check o oldTy <*> pure oldTy
408 return $ TypedValue True (ObjectUpdate o' newVals) $ Object $ rowFromList (newTys, row)
438 return $ TypedValue True (ObjectUpdate o' newVals) $ Object $ rowFromList (newTys, row)
409infer' (Accessor prop val) = do
439infer' (Accessor prop val) = do
410 typed@(TypedValue _ _ objTy) <- infer val
440 typed@(TypedValue _ _ objTy) <- infer val
@@ -424,19 +454,17 @@ infer' (Abs arg ret) = do
424 return $ TypedValue True (Abs arg body) $ function ty bodyTy
454 return $ TypedValue True (Abs arg body) $ function ty bodyTy
425infer' (App f arg) = do
455infer' (App f arg) = do
426 f'@(TypedValue _ _ ft) <- infer f
456 f'@(TypedValue _ _ ft) <- infer f
428− app <- checkFunctionApplication f' ft arg ret
457+ (ret, app) <- checkFunctionApplication f' ft arg
429 return $ TypedValue True app ret
458 return $ TypedValue True app ret
430infer' (Var var) = do
459infer' (Var var) = do
431 Just moduleName <- checkCurrentModule <$> get
460 Just moduleName <- checkCurrentModule <$> get
432− ty <- lookupVariable moduleName var
461+ ty <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< lookupVariable moduleName $ var
433− ty' <- replaceAllTypeSynonyms ty
434− case ty' of
462+ case ty of
435 ConstrainedType constraints _ -> do
463 ConstrainedType constraints _ -> do
436 env <- getEnv
464 env <- getEnv
437 dicts <- getTypeClassDictionaries
465 dicts <- getTypeClassDictionaries
438− return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty'
466+ return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty
439− _ -> return $ TypedValue True (Var var) ty'
467+ _ -> return $ TypedValue True (Var var) ty
440infer' (Block ss) = do
468infer' (Block ss) = do
441 ret <- fresh
469 ret <- fresh
442 (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
470 (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
@@ -447,7 +475,7 @@ infer' v@(Constructor c) = do
447 Just moduleName <- checkCurrentModule <$> get
475 Just moduleName <- checkCurrentModule <$> get
448 case M.lookup (qualify moduleName c) (dataConstructors env) of
476 case M.lookup (qualify moduleName c) (dataConstructors env) of
449 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
477 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
450− Just (ty, _) -> do ty' <- replaceAllTypeSynonyms ty
478+ Just (ty, _) -> do ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
451 return $ TypedValue True v ty'
479 return $ TypedValue True v ty'
452infer' (Case vals binders) = do
480infer' (Case vals binders) = do
453 ts <- mapM infer vals
481 ts <- mapM infer vals
@@ -464,9 +492,9 @@ infer' (TypedValue checkType val ty) = do
464 Just moduleName <- checkCurrentModule <$> get
492 Just moduleName <- checkCurrentModule <$> get
465 kind <- liftCheck $ kindOf moduleName ty
493 kind <- liftCheck $ kindOf moduleName ty
466 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
494 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
467− ty' <- replaceAllTypeSynonyms ty
495+ ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
468 val' <- if checkType then check val ty' else return val
496 val' <- if checkType then check val ty' else return val
469− return $ TypedValue True val' ty
497+ return $ TypedValue True val' ty'
470infer' _ = error "Invalid argument to infer"
498infer' _ = error "Invalid argument to infer"
@@ -477,9 +505,9 @@ inferProperty (Object row) prop = do
477 let (props, _) = rowToList row
505 let (props, _) = rowToList row
478 return $ lookup prop props
506 return $ lookup prop props
479inferProperty (SaturatedTypeSynonym name args) prop = do
507inferProperty (SaturatedTypeSynonym name args) prop = do
480− replaced <- expandTypeSynonym name args
508+ replaced <- introduceSkolemScope <=< expandTypeSynonym name $ args
481 inferProperty replaced prop
509 inferProperty replaced prop
482−inferProperty (ForAll ident ty) prop = do
510+inferProperty (ForAll ident ty _) prop = do
483 replaced <- replaceVarWithUnknown ident ty
511 replaced <- replaceVarWithUnknown ident ty
484 inferProperty replaced prop
512 inferProperty replaced prop
485inferProperty _ _ = return Nothing
513inferProperty _ _ = return Nothing
@@ -551,7 +579,7 @@ checkBinders nvals ret ((binders, grd, val):bs) = do
551 Just moduleName <- checkCurrentModule <$> get
579 Just moduleName <- checkCurrentModule <$> get
552 m1 <- M.unions <$> zipWithM inferBinder nvals binders
580 m1 <- M.unions <$> zipWithM inferBinder nvals binders
553 r <- bindLocalVariables moduleName (M.toList m1) $ do
581 r <- bindLocalVariables moduleName (M.toList m1) $ do
554− val' <- check val ret
582+ val' <- TypedValue True <$> check val ret <*> pure ret
555 case grd of
583 case grd of
556 Nothing -> return (binders, Nothing, val')
584 Nothing -> return (binders, Nothing, val')
557 Just g -> do
585 Just g -> do
@@ -602,7 +630,7 @@ checkStatement mass ret (For ident start end inner) = do
602 return (allCodePathsReturn, mass, For ident start' end' inner')
630 return (allCodePathsReturn, mass, For ident start' end' inner')
603checkStatement mass ret (Return val) = do
631checkStatement mass ret (Return val) = do
604 val' <- check val ret
632 val' <- check val ret
605− return (True, mass, Return val')
633+ return (True, mass, Return (TypedValue True val' ret))
608-- Check the type of an if-then-else statement
636-- Check the type of an if-then-else statement
@@ -642,13 +670,32 @@ checkBlock mass ret (s:ss) = do
642 (b, m, ss'') <- checkBlock mass1 ret ss'
670 (b, m, ss'') <- checkBlock mass1 ret ss'
643 return (b, m, s':ss'')
671 return (b, m, s':ss'')
674+-- Generate a new skolem constant
676+newSkolemConstant :: UnifyT Type Check Int
677+newSkolemConstant = runUnknown <$> fresh'
680+-- Generate a new skolem scope
682+newSkolemScope :: UnifyT Type Check SkolemScope
683+newSkolemScope = SkolemScope . runUnknown <$> fresh'
646-- Skolemize a type variable by replacing its instances with fresh skolem constants
686-- Skolemize a type variable by replacing its instances with fresh skolem constants
688+skolemize :: (D.Data d) => String -> Int -> SkolemScope -> d -> d
689+skolemize ident sko scope d = replaceTypeVars ident (Skolem sko scope) d
692+-- Introduce skolem scope at every occurence of a ForAll
648−skolemize :: String -> Type -> UnifyT Type Check Type
694+introduceSkolemScope :: Type -> UnifyT Type Check Type
649−skolemize ident ty = do
695+introduceSkolemScope = everywhereM (mkM go)
650− tsk <- Skolem . runUnknown <$> fresh'
696+ where
651− return $ replaceTypeVars ident tsk ty
697+ go (ForAll ident ty Nothing) = ForAll ident ty <$> (Just <$> newSkolemScope)
698+ go other = return other
654-- Check the type of a value, rethrowing errors to provide a better error message
701-- Check the type of a value, rethrowing errors to provide a better error message
@@ -668,10 +715,13 @@ check val ty = rethrow errorMessage $ check' val ty
668-- Check the type of a value
715-- Check the type of a value
670check' :: Value -> Type -> UnifyT Type Check Value
717check' :: Value -> Type -> UnifyT Type Check Value
671−check' val (ForAll idents ty) = do
718+check' val t@(ForAll ident ty _) = do
719+ scope <- newSkolemScope
720+ sko <- newSkolemConstant
672− sk <- skolemize idents ty
721+ let sk = skolemize ident sko scope ty
673− check val sk
722+ val' <- check val sk
723+ return $ TypedValue True val' (ForAll ident ty (Just scope))
674−check' val (ConstrainedType constraints ty) = do
724+check' val t@(ConstrainedType constraints ty) = do
675 env <- getEnv
725 env <- getEnv
676 Just moduleName <- checkCurrentModule <$> get
726 Just moduleName <- checkCurrentModule <$> get
677 dictNames <- flip mapM constraints $ \(Qualified _ (ProperName className), _) -> do
727 dictNames <- flip mapM constraints $ \(Qualified _ (ProperName className), _) -> do
@@ -681,34 +731,43 @@ check' val (ConstrainedType constraints ty) = do
681 TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular) (map (Qualified Nothing) dictNames)
731 TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular) (map (Qualified Nothing) dictNames)
682 (qualifyAllUnqualifiedNames moduleName env constraints)) $
732 (qualifyAllUnqualifiedNames moduleName env constraints)) $
683 check val ty
733 check val ty
684− return $ foldr Abs val' dictNames
734+ return $ TypedValue True (foldr Abs val' dictNames) t
735+check' val t@(SaturatedTypeSynonym name args) = do
736+ ty <- introduceSkolemScope <=< expandTypeSynonym name $ args
737+ val' <- check val ty
738+ return $ TypedValue True val' ty
685check' val u@(TUnknown _) = do
739check' val u@(TUnknown _) = do
686 val'@(TypedValue _ _ ty) <- infer val
740 val'@(TypedValue _ _ ty) <- infer val
687 -- Don't unify an unknown with an inferred polytype
741 -- Don't unify an unknown with an inferred polytype
688 ty' <- replaceAllVarsWithUnknowns ty
742 ty' <- replaceAllVarsWithUnknowns ty
689 ty' =?= u
743 ty' =?= u
690− return val'
744+ return $ TypedValue True val' ty'
691−check' v@(NumericLiteral _) t | t == tyNumber = return v
745+check' v@(NumericLiteral _) t | t == tyNumber =
746+ return $ TypedValue True v t
692−check' v@(StringLiteral _) t | t == tyString = return v
747+check' v@(StringLiteral _) t | t == tyString =
748+ return $ TypedValue True v t
693−check' v@(BooleanLiteral _) t | t == tyBoolean = return v
749+check' v@(BooleanLiteral _) t | t == tyBoolean =
750+ return $ TypedValue True v t
694−check' (ArrayLiteral vals) (TypeApp a ty) | a == tyArray = ArrayLiteral <$> forM vals (\val -> check val ty)
751+check' (ArrayLiteral vals) t@(TypeApp a ty) | a == tyArray = do
752+ arr <- ArrayLiteral <$> forM vals (\val -> check val ty)
753+ return $ TypedValue True arr t
695−check' (Abs arg ret) (TypeApp (TypeApp t argTy) retTy) | t == tyFunction = do
754+check' (Abs arg ret) ty@(TypeApp (TypeApp t argTy) retTy) | t == tyFunction = do
696 Just moduleName <- checkCurrentModule <$> get
755 Just moduleName <- checkCurrentModule <$> get
697 ret' <- bindLocalVariables moduleName [(arg, argTy)] $ check ret retTy
756 ret' <- bindLocalVariables moduleName [(arg, argTy)] $ check ret retTy
698− return $ Abs arg ret'
757+ return $ TypedValue True (Abs arg ret') ty
699check' (App f arg) ret = do
758check' (App f arg) ret = do
700 f'@(TypedValue _ _ ft) <- infer f
759 f'@(TypedValue _ _ ft) <- infer f
701− app <- checkFunctionApplication f' ft arg ret
760+ (ret', app) <- checkFunctionApplication f' ft arg
761+ subsumes Nothing ret' ret
702− return $ app
762+ return $ TypedValue True app ret
703check' v@(Var var) ty = do
763check' v@(Var var) ty = do
704 Just moduleName <- checkCurrentModule <$> get
764 Just moduleName <- checkCurrentModule <$> get
705− ty1 <- lookupVariable moduleName var
765+ repl <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< lookupVariable moduleName $ var
706− repl <- replaceAllTypeSynonyms ty1
707− ty' <- replaceAllTypeSynonyms ty
766+ ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
708 v' <- subsumes (Just v) repl ty'
767 v' <- subsumes (Just v) repl ty'
709 case v' of
768 case v' of
710 Nothing -> throwError "Unable to check type subsumption"
769 Nothing -> throwError "Unable to check type subsumption"
711− Just v'' -> return v''
770+ Just v'' -> return $ TypedValue True v'' ty'
712check' (TypedValue checkType val ty1) ty2 = do
771check' (TypedValue checkType val ty1) ty2 = do
713 Just moduleName <- checkCurrentModule <$> get
772 Just moduleName <- checkCurrentModule <$> get
714 kind <- liftCheck $ kindOf moduleName ty1
773 kind <- liftCheck $ kindOf moduleName ty1
@@ -718,22 +777,22 @@ check' (TypedValue checkType val ty1) ty2 = do
718 Nothing -> throwError "Unable to check type subsumption"
777 Nothing -> throwError "Unable to check type subsumption"
719 Just val'' -> do
778 Just val'' -> do
720 val''' <- if checkType then check val'' ty1 else return val''
779 val''' <- if checkType then check val'' ty1 else return val''
721− return $ TypedValue True val''' ty1
780+ return $ TypedValue checkType (TypedValue True val''' ty1) ty2
722check' (Case vals binders) ret = do
781check' (Case vals binders) ret = do
723 vals' <- mapM infer vals
782 vals' <- mapM infer vals
724 let ts = map (\(TypedValue _ _ t) -> t) vals'
783 let ts = map (\(TypedValue _ _ t) -> t) vals'
725 binders' <- checkBinders ts ret binders
784 binders' <- checkBinders ts ret binders
726− return $ Case vals' binders'
785+ return $ TypedValue True (Case vals' binders') ret
727check' (IfThenElse cond th el) ty = do
786check' (IfThenElse cond th el) ty = do
728 cond' <- check cond tyBoolean
787 cond' <- check cond tyBoolean
729 th' <- check th ty
788 th' <- check th ty
730 el' <- check el ty
789 el' <- check el ty
731− return $ IfThenElse cond' th' el'
790+ return $ TypedValue True (IfThenElse cond' th' el') ty
732−check' (ObjectLiteral ps) (Object row) = do
791+check' (ObjectLiteral ps) t@(Object row) = do
733 ensureNoDuplicateProperties ps
792 ensureNoDuplicateProperties ps
734 ps' <- checkProperties ps row False
793 ps' <- checkProperties ps row False
735− return $ ObjectLiteral ps'
794+ return $ TypedValue True (ObjectLiteral ps') t
736−check' (ObjectUpdate obj ps) (Object row) = do
795+check' (ObjectUpdate obj ps) t@(Object row) = do
737 ensureNoDuplicateProperties ps
796 ensureNoDuplicateProperties ps
738 us <- zip (map fst ps) <$> replicateM (length ps) fresh
797 us <- zip (map fst ps) <$> replicateM (length ps) fresh
739 let (propsToCheck, rest) = rowToList row
798 let (propsToCheck, rest) = rowToList row
@@ -741,27 +800,24 @@ check' (ObjectUpdate obj ps) (Object row) = do
741 remainingProps = filter (\(p, _) -> p `notElem` propsToRemove) propsToCheck
800 remainingProps = filter (\(p, _) -> p `notElem` propsToRemove) propsToCheck
742 obj' <- check obj (Object (rowFromList (us ++ remainingProps, rest)))
801 obj' <- check obj (Object (rowFromList (us ++ remainingProps, rest)))
743 ps' <- checkProperties ps row True
802 ps' <- checkProperties ps row True
744− return $ ObjectUpdate obj' ps'
803+ return $ TypedValue True (ObjectUpdate obj' ps') t
745check' (Accessor prop val) ty = do
804check' (Accessor prop val) ty = do
746 rest <- fresh
805 rest <- fresh
747 val' <- check val (Object (RCons prop ty rest))
806 val' <- check val (Object (RCons prop ty rest))
748− return $ Accessor prop val'
807+ return $ TypedValue True (Accessor prop val') ty
749check' (Block ss) ret = do
808check' (Block ss) ret = do
750 (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
809 (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
751 guardWith "Block is missing a return statement" allCodePathsReturn
810 guardWith "Block is missing a return statement" allCodePathsReturn
752− return $ Block ss'
811+ return $ TypedValue True (Block ss') ret
753check' (Constructor c) ty = do
812check' (Constructor c) ty = do
754 env <- getEnv
813 env <- getEnv
755 Just moduleName <- checkCurrentModule <$> get
814 Just moduleName <- checkCurrentModule <$> get
756 case M.lookup (qualify moduleName c) (dataConstructors env) of
815 case M.lookup (qualify moduleName c) (dataConstructors env) of
757 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
816 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
758 Just (ty1, _) -> do
817 Just (ty1, _) -> do
759− repl <- replaceAllTypeSynonyms ty1
818+ repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
760 _ <- subsumes Nothing repl ty
819 _ <- subsumes Nothing repl ty
761− return $ Constructor c
820+ return $ TypedValue True (Constructor c) ty
762−check' val (SaturatedTypeSynonym name args) = do
763− ty <- expandTypeSynonym name args
765check' val ty = throwError $ prettyPrintValue val ++ " does not have type " ++ prettyPrintType ty
821check' val ty = throwError $ prettyPrintValue val ++ " does not have type " ++ prettyPrintType ty
@@ -774,7 +830,7 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
774 go [] [] REmpty = return []
830 go [] [] REmpty = return []
775 go [] [] u@(TUnknown _) = do u =?= REmpty
831 go [] [] u@(TUnknown _) = do u =?= REmpty
776 return []
832 return []
777− go [] [] (Skolem _) | lax = return []
833+ go [] [] (Skolem _ _) | lax = return []
778 go [] ((p, _): _) _ | lax = return []
834 go [] ((p, _): _) _ | lax = return []
779 | otherwise = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have property " ++ p
835 | otherwise = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have property " ++ p
780 go ((p,_):_) [] REmpty = throwError $ "Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row
836 go ((p,_):_) [] REmpty = throwError $ "Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row
@@ -801,8 +857,8 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
802-- Check the type of a function application, rethrowing errors to provide a better error message
858-- Check the type of a function application, rethrowing errors to provide a better error message
804−checkFunctionApplication :: Value -> Type -> Value -> Type -> UnifyT Type Check Value
860+checkFunctionApplication :: Value -> Type -> Value -> UnifyT Type Check (Type, Value)
805−checkFunctionApplication fn fnTy arg ret = rethrow errorMessage $ checkFunctionApplication' fn fnTy arg ret
861+checkFunctionApplication fn fnTy arg = rethrow errorMessage $ checkFunctionApplication' fn fnTy arg
807 errorMessage msg = "Error applying function of type "
863 errorMessage msg = "Error applying function of type "
808 ++ prettyPrintType fnTy
864 ++ prettyPrintType fnTy
@@ -812,34 +868,33 @@ checkFunctionApplication fn fnTy arg ret = rethrow errorMessage $ checkFunctionA
813-- Check the type of a function application
869-- Check the type of a function application
815−checkFunctionApplication' :: Value -> Type -> Value -> Type -> UnifyT Type Check Value
871+checkFunctionApplication' :: Value -> Type -> Value -> UnifyT Type Check (Type, Value)
816−checkFunctionApplication' fn (TypeApp (TypeApp tyFunction' argTy) retTy) arg ret = do
872+checkFunctionApplication' fn (TypeApp (TypeApp tyFunction' argTy) retTy) arg = do
817 tyFunction' =?= tyFunction
873 tyFunction' =?= tyFunction
818 arg' <- check arg argTy
874 arg' <- check arg argTy
819− _ <- subsumes Nothing retTy ret
820− return $ App fn arg'
875+ return (retTy, App fn arg')
821−checkFunctionApplication' fn (ForAll ident ty) arg ret = do
876+checkFunctionApplication' fn (ForAll ident ty _) arg = do
822 replaced <- replaceVarWithUnknown ident ty
877 replaced <- replaceVarWithUnknown ident ty
823− checkFunctionApplication fn replaced arg ret
878+ checkFunctionApplication fn replaced arg
824−checkFunctionApplication' fn u@(TUnknown _) arg ret = do
879+checkFunctionApplication' fn u@(TUnknown _) arg = do
825 arg' <- do
880 arg' <- do
826 TypedValue _ v t <- infer arg
881 TypedValue _ v t <- infer arg
827 TypedValue True v <$> replaceAllVarsWithUnknowns t
882 TypedValue True v <$> replaceAllVarsWithUnknowns t
828 let ty = (\(TypedValue _ _ t) -> t) arg'
883 let ty = (\(TypedValue _ _ t) -> t) arg'
829 u =?= function ty ret
885 u =?= function ty ret
830− return $ App fn arg'
886+ return (ret, App fn arg')
831−checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do
887+checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg = do
832− ty <- expandTypeSynonym name tyArgs
888+ ty <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
833− checkFunctionApplication fn ty arg ret
889+ checkFunctionApplication fn ty arg
834−checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
890+checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg = do
835 env <- getEnv
891 env <- getEnv
836 dicts <- getTypeClassDictionaries
892 dicts <- getTypeClassDictionaries
837 Just moduleName <- checkCurrentModule <$> get
893 Just moduleName <- checkCurrentModule <$> get
838− checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) fnTy arg ret
894+ checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) fnTy arg
839−checkFunctionApplication' _ fnTy arg ret = throwError $ "Applying a function of type "
895+checkFunctionApplication' _ fnTy arg = throwError $ "Cannot apply a function of type "
840 ++ prettyPrintType fnTy
896 ++ prettyPrintType fnTy
841− ++ " to argument(s) " ++ prettyPrintValue arg
897+ ++ " to argument " ++ prettyPrintValue arg
842− ++ " does not yield a value of type " ++ prettyPrintType ret ++ "."
845-- Check whether one type subsumes another, rethrowing errors to provide a better error message
900-- Check whether one type subsumes another, rethrowing errors to provide a better error message
@@ -857,18 +912,25 @@ subsumes val ty1 ty2 = rethrow errorMessage $ subsumes' val ty1 ty2
857-- Check whether one type subsumes another
912-- Check whether one type subsumes another
859subsumes' :: Maybe Value -> Type -> Type -> UnifyT Type Check (Maybe Value)
914subsumes' :: Maybe Value -> Type -> Type -> UnifyT Type Check (Maybe Value)
860−subsumes' val (ForAll ident ty1) ty2 = do
915+subsumes' val (ForAll ident ty1 _) ty2 = do
861 replaced <- replaceVarWithUnknown ident ty1
916 replaced <- replaceVarWithUnknown ident ty1
862 subsumes val replaced ty2
917 subsumes val replaced ty2
918+subsumes' val ty1 (ForAll ident ty2 sco) =
921+ sko <- newSkolemConstant
922+ let sk = skolemize ident sko sco' ty2
924+ Nothing -> throwError "Skolem variable scope is unspecified"
863subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do
925subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do
864 subsumes Nothing arg2 arg1
926 subsumes Nothing arg2 arg1
865 subsumes Nothing ret1 ret2
927 subsumes Nothing ret1 ret2
866 return val
928 return val
867subsumes' val (SaturatedTypeSynonym name tyArgs) ty2 = do
929subsumes' val (SaturatedTypeSynonym name tyArgs) ty2 = do
868− ty1 <- expandTypeSynonym name tyArgs
930+ ty1 <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
869 subsumes val ty1 ty2
931 subsumes val ty1 ty2
870subsumes' val ty1 (SaturatedTypeSynonym name tyArgs) = do
932subsumes' val ty1 (SaturatedTypeSynonym name tyArgs) = do
871− ty2 <- expandTypeSynonym name tyArgs
933+ ty2 <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
872 subsumes val ty1 ty2
934 subsumes val ty1 ty2
873subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
935subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
874 env <- getEnv
936 env <- getEnv