@@ -45,7 +45,8 @@ import Data.List
4545import Data.Maybe (maybeToList, isNothing, isJust, fromMaybe)
4646import qualified Data.Data as D
4747import Data.Generics
48− (mkM, everywhereM, everything, mkT, something, everywhere, mkQ)
48+ (everythingWithContext, mkM, everywhereM, everything, mkT,
49+ something, everywhere, mkQ)
4950
5051import Language.PureScript.Values
5152import Language.PureScript.Types
@@ -66,6 +67,7 @@ import Control.Arrow (Arrow(..))
6667
6768import qualified Data.Map as M
6869import Data.Function (on)
70+import Debug.Trace (trace)
6971
7072instance Partial Type where
7173 unknown = TUnknown
@@ -86,17 +88,23 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
8688 unifyTypes' (TUnknown u) t = u =:= t
8789 unifyTypes' t (TUnknown u) = u =:= t
8890 unifyTypes' (SaturatedTypeSynonym name args) ty = do
89− ty1 <- expandTypeSynonym name args
91+ ty1 <- introduceSkolemScope <=< expandTypeSynonym name $ args
9092 ty1 `unifyTypes` ty
9193 unifyTypes' ty s@(SaturatedTypeSynonym _ _) = s `unifyTypes` ty
92− unifyTypes' (ForAll ident1 ty1) (ForAll ident2 ty2) = do
93− sk <- skolemize ident1 ty1
94− replaced <- replaceVarWithUnknown ident2 ty2
95− sk `unifyTypes` replaced
96− unifyTypes' (ForAll ident ty1) ty2 = do
97− sk <- skolemize ident ty1
94+ unifyTypes' (ForAll ident1 ty1 sc1) (ForAll ident2 ty2 sc2) =
95+ case (sc1, sc2) of
96+ (Just sc1', Just sc2') -> do
97+ sko <- newSkolemConstant
98+ let sk1 = skolemize ident1 sko sc1' ty1
99+ let sk2 = skolemize ident2 sko sc2' ty2
100+ sk1 `unifyTypes` sk2
101+ _ -> throwError (prettyPrintType ty1)
102+ unifyTypes' (ForAll ident ty1 (Just sc)) ty2 = do
103+ sko <- newSkolemConstant
104+ let sk = skolemize ident sko sc ty1
98105 sk `unifyTypes` ty2
99− unifyTypes' ty f@(ForAll _ _) = f `unifyTypes` ty
106+ unifyTypes' (ForAll _ _ _) _ = throwError "Skolem variable scope is unspecified"
107+ unifyTypes' ty f@(ForAll _ _ _) = f `unifyTypes` ty
100108 unifyTypes' (Object row1) (Object row2) = row1 =?= row2
101109 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
102110 unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do
@@ -106,7 +114,7 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
106114 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
107115 t3 `unifyTypes` t5
108116 t4 `unifyTypes` t6
109− unifyTypes' (Skolem s1) (Skolem s2) | s1 == s2 = return ()
117+ unifyTypes' (Skolem s1 _) (Skolem s2 _) | s1 == s2 = return ()
110118 unifyTypes' r1@(RCons _ _ _) r2 = unifyRows r1 r2
111119 unifyTypes' r1 r2@(RCons _ _ _) = unifyRows r1 r2
112120 unifyTypes' r1@REmpty r2 = unifyRows r1 r2
@@ -143,7 +151,7 @@ unifyRows r1 r2 =
143151 unifyRows' row r others u'
144152 unifyRows' [] REmpty [] REmpty = return ()
145153 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 ()
147155 unifyRows' sd3 r3 sd4 r4 = throwError $ "Cannot unify " ++ prettyPrintRow (rowFromList (sd3, r3)) ++ " with " ++ prettyPrintRow (rowFromList (sd4, r4)) ++ "."
148156
149157-- |
@@ -171,22 +179,24 @@ typesOf moduleName vals = do
171179 (ident, (val, Just (ty, checkType))) -> do
172180 kind <- liftCheck $ kindOf moduleName ty
173181 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
174− ty' <- replaceAllTypeSynonyms ty
175− val' <- bindNames dict $ if checkType then check val ty' else return val
182+ ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
183+ val' <- bindNames dict $ if checkType
184+ then TypedValue True <$> check val ty' <*> pure ty'
185+ else return (TypedValue False val ty')
176186 return (ident, (val', ty'))
177187 (ident, (val, Nothing)) -> do
178188 TypedValue _ val' ty <- bindNames dict $ infer val
179189 ty =?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
180− return (ident, (val', ty))
190+ return (ident, (TypedValue True val' ty, ty))
181191 when (moduleName == ModuleName (ProperName "Main") && fst e == Ident "main") $ do
182192 [eff, a] <- replicateM 2 fresh
183193 ty =?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName (ProperName "Eff"))) (ProperName "Eff"))) eff) a
184194 escapeCheck val ty
185195 return triple
186− forM_ tys $ skolemEscapeCheck . snd . snd
187196 forM tys $ \(ident, (val, ty)) -> do
188197 val' <- replaceTypeClassDictionaries moduleName val
189− return (ident, (overTypes (desaturateAllTypeSynonyms . setifyAll) $ val'
198+ rethrow (("Error in " ++ show ident ++ ": \n") ++) $ skolemEscapeCheck val'
199+ return $ (ident, (overTypes (desaturateAllTypeSynonyms . setifyAll) $ val'
190200 , varIfUnknown . desaturateAllTypeSynonyms . setifyAll $ ty))
191201 where
192202 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
238248 return $ Just dict
239249 mkDictionary :: Qualified Ident -> Maybe [Value] -> Value
240250 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
242252 filterModule :: TypeClassDictionaryInScope -> Bool
243253 filterModule (TypeClassDictionaryInScope { tcdName = Qualified (Just mn) _ }) | mn == moduleName = True
244254 filterModule (TypeClassDictionaryInScope { tcdName = Qualified Nothing _ }) = True
@@ -252,7 +262,9 @@ entails moduleName context goal@(className, ty) = do
252262-- and return a substitution from type variables to types which makes the type heads unify.
253263--
254264typeHeadsAreEqual :: 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)]
256268typeHeadsAreEqual m e (TypeConstructor c1) (TypeConstructor c2) | typeConstructorsAreEqual e m c1 c2 = Just []
257269typeHeadsAreEqual m e (TypeApp h1 (TypeVar v)) (TypeApp h2 arg) = (:) (v, arg) <$> typeHeadsAreEqual m e h1 h2
258270typeHeadsAreEqual m e t1@(TypeApp _ _) t2@(TypeApp _ (TypeVar _)) = typeHeadsAreEqual m e t2 t1
@@ -268,7 +280,7 @@ escapeCheck value ty = do
268280 let allUnknowns = findAllTypes value
269281 forM_ allUnknowns $ \t -> do
270282 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
272284
273285-- |
274286-- Find all type annotations occuring inside a value
@@ -282,14 +294,31 @@ findAllTypes = everything (++) (mkQ [] go)
282294-- |
283295-- Ensure skolem variables do not escape their scope
284296--
285−skolemEscapeCheck :: Type -> Check ()
286−skolemEscapeCheck ty =
287− case something (mkQ Nothing findSkolems) ty of
288− Nothing -> return ()
289− Just _ -> throwError $ "Skolem variables cannot escape. Consider adding a type signature."
297+skolemEscapeCheck :: Value -> Check ()
298+skolemEscapeCheck (TypedValue False _ _) = return ()
299+skolemEscapeCheck root@(TypedValue _ _ _) =
300+ case everythingWithContext [] (++) (mkQ ((,) []) go) root of
301+ [] -> return ()
302+ ((binding, val) : _) -> throwError $ "Rigid/skolem type variable bound by " ++ maybe "<unknown>" prettyPrintValue binding ++ " has escaped at " ++ prettyPrintValue val
290303 where
291− findSkolems (Skolem _) = return ()
292− findSkolems _ = mzero
304+ go :: Value -> [(SkolemScope, Value)] -> ([(Maybe Value, Value)], [(SkolemScope, Value)])
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)
308+ _ -> ([], scos)
309+ where
310+ collectSkolems :: Type -> [SkolemScope]
311+ collectSkolems = nub . everything (++) (mkQ [] collect)
312+ where
313+ collect (Skolem _ scope) = [scope]
314+ collect _ = []
315+ go _ scos = ([], scos)
316+ findBindingScope :: SkolemScope -> Maybe Value
317+ findBindingScope sco = something (mkQ Nothing go) root
318+ where
319+ go val@(TypedValue _ _ (ForAll _ _ (Just sco'))) | sco == sco' = Just val
320+ go _ = Nothing
321+skolemEscapeCheck val = throwError $ "Untyped value passed to skolemEscapeCheck: " ++ prettyPrintValue val
293322
294323-- |
295324-- Ensure a row contains no duplicate labels
@@ -326,7 +355,7 @@ replaceAllTypeVars = foldl' (\f (name, ty) -> replaceTypeVars name ty . f) id
326355-- Replace named type variables with new unification variables
327356--
328357replaceAllVarsWithUnknowns :: Type -> UnifyT Type Check Type
329−replaceAllVarsWithUnknowns (ForAll ident ty) = replaceVarWithUnknown ident ty >>= replaceAllVarsWithUnknowns
358+replaceAllVarsWithUnknowns (ForAll ident ty _) = replaceVarWithUnknown ident ty >>= replaceAllVarsWithUnknowns
330359replaceAllVarsWithUnknowns ty = return ty
331360
332361-- |
@@ -404,7 +433,8 @@ infer' (ObjectUpdate o ps) = do
404433 newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> mapM (infer . snd) ps
405434 let newTys = map (\(name, TypedValue _ _ ty) -> (name, ty)) newVals
406435 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
408438 return $ TypedValue True (ObjectUpdate o' newVals) $ Object $ rowFromList (newTys, row)
409439infer' (Accessor prop val) = do
410440 typed@(TypedValue _ _ objTy) <- infer val
@@ -424,19 +454,17 @@ infer' (Abs arg ret) = do
424454 return $ TypedValue True (Abs arg body) $ function ty bodyTy
425455infer' (App f arg) = do
426456 f'@(TypedValue _ _ ft) <- infer f
427− ret <- fresh
428− app <- checkFunctionApplication f' ft arg ret
457+ (ret, app) <- checkFunctionApplication f' ft arg
429458 return $ TypedValue True app ret
430459infer' (Var var) = do
431460 Just moduleName <- checkCurrentModule <$> get
432− ty <- lookupVariable moduleName var
433− ty' <- replaceAllTypeSynonyms ty
434− case ty' of
461+ ty <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< lookupVariable moduleName $ var
462+ case ty of
435463 ConstrainedType constraints _ -> do
436464 env <- getEnv
437465 dicts <- getTypeClassDictionaries
438− return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty'
439− _ -> return $ TypedValue True (Var var) ty'
466+ return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty
467+ _ -> return $ TypedValue True (Var var) ty
440468infer' (Block ss) = do
441469 ret <- fresh
442470 (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
@@ -447,7 +475,7 @@ infer' v@(Constructor c) = do
447475 Just moduleName <- checkCurrentModule <$> get
448476 case M.lookup (qualify moduleName c) (dataConstructors env) of
449477 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
450− Just (ty, _) -> do ty' <- replaceAllTypeSynonyms ty
478+ Just (ty, _) -> do ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
451479 return $ TypedValue True v ty'
452480infer' (Case vals binders) = do
453481 ts <- mapM infer vals
@@ -464,9 +492,9 @@ infer' (TypedValue checkType val ty) = do
464492 Just moduleName <- checkCurrentModule <$> get
465493 kind <- liftCheck $ kindOf moduleName ty
466494 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
467− ty' <- replaceAllTypeSynonyms ty
495+ ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
468496 val' <- if checkType then check val ty' else return val
469− return $ TypedValue True val' ty
497+ return $ TypedValue True val' ty'
470498infer' _ = error "Invalid argument to infer"
471499
472500-- |
@@ -477,9 +505,9 @@ inferProperty (Object row) prop = do
477505 let (props, _) = rowToList row
478506 return $ lookup prop props
479507inferProperty (SaturatedTypeSynonym name args) prop = do
480− replaced <- expandTypeSynonym name args
508+ replaced <- introduceSkolemScope <=< expandTypeSynonym name $ args
481509 inferProperty replaced prop
482−inferProperty (ForAll ident ty) prop = do
510+inferProperty (ForAll ident ty _) prop = do
483511 replaced <- replaceVarWithUnknown ident ty
484512 inferProperty replaced prop
485513inferProperty _ _ = return Nothing
@@ -551,7 +579,7 @@ checkBinders nvals ret ((binders, grd, val):bs) = do
551579 Just moduleName <- checkCurrentModule <$> get
552580 m1 <- M.unions <$> zipWithM inferBinder nvals binders
553581 r <- bindLocalVariables moduleName (M.toList m1) $ do
554− val' <- check val ret
582+ val' <- TypedValue True <$> check val ret <*> pure ret
555583 case grd of
556584 Nothing -> return (binders, Nothing, val')
557585 Just g -> do
@@ -602,7 +630,7 @@ checkStatement mass ret (For ident start end inner) = do
602630 return (allCodePathsReturn, mass, For ident start' end' inner')
603631checkStatement mass ret (Return val) = do
604632 val' <- check val ret
605− return (True, mass, Return val')
633+ return (True, mass, Return (TypedValue True val' ret))
606634
607635-- |
608636-- Check the type of an if-then-else statement
@@ -642,13 +670,32 @@ checkBlock mass ret (s:ss) = do
642670 (b, m, ss'') <- checkBlock mass1 ret ss'
643671 return (b, m, s':ss'')
644672
673+-- |
674+-- Generate a new skolem constant
675+--
676+newSkolemConstant :: UnifyT Type Check Int
677+newSkolemConstant = runUnknown <$> fresh'
678+
679+-- |
680+-- Generate a new skolem scope
681+--
682+newSkolemScope :: UnifyT Type Check SkolemScope
683+newSkolemScope = SkolemScope . runUnknown <$> fresh'
684+
645685-- |
646686-- Skolemize a type variable by replacing its instances with fresh skolem constants
647687--
648−skolemize :: String -> Type -> UnifyT Type Check Type
649−skolemize ident ty = do
650− tsk <- Skolem . runUnknown <$> fresh'
651− return $ replaceTypeVars ident tsk ty
688+skolemize :: (D.Data d) => String -> Int -> SkolemScope -> d -> d
689+skolemize ident sko scope d = replaceTypeVars ident (Skolem sko scope) d
690+
691+-- |
692+-- Introduce skolem scope at every occurence of a ForAll
693+--
694+introduceSkolemScope :: Type -> UnifyT Type Check Type
695+introduceSkolemScope = everywhereM (mkM go)
696+ where
697+ go (ForAll ident ty Nothing) = ForAll ident ty <$> (Just <$> newSkolemScope)
698+ go other = return other
652699
653700-- |
654701-- 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
668715-- Check the type of a value
669716--
670717check' :: Value -> Type -> UnifyT Type Check Value
671−check' val (ForAll idents ty) = do
672− sk <- skolemize idents ty
673− check val sk
674−check' val (ConstrainedType constraints ty) = do
718+check' val t@(ForAll ident ty _) = do
719+ scope <- newSkolemScope
720+ sko <- newSkolemConstant
721+ let sk = skolemize ident sko scope ty
722+ val' <- check val sk
723+ return $ TypedValue True val' (ForAll ident ty (Just scope))
724+check' val t@(ConstrainedType constraints ty) = do
675725 env <- getEnv
676726 Just moduleName <- checkCurrentModule <$> get
677727 dictNames <- flip mapM constraints $ \(Qualified _ (ProperName className), _) -> do
@@ -681,34 +731,43 @@ check' val (ConstrainedType constraints ty) = do
681731 TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular) (map (Qualified Nothing) dictNames)
682732 (qualifyAllUnqualifiedNames moduleName env constraints)) $
683733 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
685739check' val u@(TUnknown _) = do
686740 val'@(TypedValue _ _ ty) <- infer val
687741 -- Don't unify an unknown with an inferred polytype
688742 ty' <- replaceAllVarsWithUnknowns ty
689743 ty' =?= u
690− return val'
691−check' v@(NumericLiteral _) t | t == tyNumber = return v
692−check' v@(StringLiteral _) t | t == tyString = return v
693−check' v@(BooleanLiteral _) t | t == tyBoolean = return v
694−check' (ArrayLiteral vals) (TypeApp a ty) | a == tyArray = ArrayLiteral <$> forM vals (\val -> check val ty)
695−check' (Abs arg ret) (TypeApp (TypeApp t argTy) retTy) | t == tyFunction = do
744+ return $ TypedValue True val' ty'
745+check' v@(NumericLiteral _) t | t == tyNumber =
746+ return $ TypedValue True v t
747+check' v@(StringLiteral _) t | t == tyString =
748+ return $ TypedValue True v t
749+check' v@(BooleanLiteral _) t | t == tyBoolean =
750+ return $ TypedValue True v t
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
754+check' (Abs arg ret) ty@(TypeApp (TypeApp t argTy) retTy) | t == tyFunction = do
696755 Just moduleName <- checkCurrentModule <$> get
697756 ret' <- bindLocalVariables moduleName [(arg, argTy)] $ check ret retTy
698− return $ Abs arg ret'
757+ return $ TypedValue True (Abs arg ret') ty
699758check' (App f arg) ret = do
700759 f'@(TypedValue _ _ ft) <- infer f
701− app <- checkFunctionApplication f' ft arg ret
702− return $ app
760+ (ret', app) <- checkFunctionApplication f' ft arg
761+ subsumes Nothing ret' ret
762+ return $ TypedValue True app ret
703763check' v@(Var var) ty = do
704764 Just moduleName <- checkCurrentModule <$> get
705− ty1 <- lookupVariable moduleName var
706− repl <- replaceAllTypeSynonyms ty1
707− ty' <- replaceAllTypeSynonyms ty
765+ repl <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< lookupVariable moduleName $ var
766+ ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
708767 v' <- subsumes (Just v) repl ty'
709768 case v' of
710769 Nothing -> throwError "Unable to check type subsumption"
711− Just v'' -> return v''
770+ Just v'' -> return $ TypedValue True v'' ty'
712771check' (TypedValue checkType val ty1) ty2 = do
713772 Just moduleName <- checkCurrentModule <$> get
714773 kind <- liftCheck $ kindOf moduleName ty1
@@ -718,22 +777,22 @@ check' (TypedValue checkType val ty1) ty2 = do
718777 Nothing -> throwError "Unable to check type subsumption"
719778 Just val'' -> do
720779 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
722781check' (Case vals binders) ret = do
723782 vals' <- mapM infer vals
724783 let ts = map (\(TypedValue _ _ t) -> t) vals'
725784 binders' <- checkBinders ts ret binders
726− return $ Case vals' binders'
785+ return $ TypedValue True (Case vals' binders') ret
727786check' (IfThenElse cond th el) ty = do
728787 cond' <- check cond tyBoolean
729788 th' <- check th ty
730789 el' <- check el ty
731− return $ IfThenElse cond' th' el'
732−check' (ObjectLiteral ps) (Object row) = do
790+ return $ TypedValue True (IfThenElse cond' th' el') ty
791+check' (ObjectLiteral ps) t@(Object row) = do
733792 ensureNoDuplicateProperties ps
734793 ps' <- checkProperties ps row False
735− return $ ObjectLiteral ps'
736−check' (ObjectUpdate obj ps) (Object row) = do
794+ return $ TypedValue True (ObjectLiteral ps') t
795+check' (ObjectUpdate obj ps) t@(Object row) = do
737796 ensureNoDuplicateProperties ps
738797 us <- zip (map fst ps) <$> replicateM (length ps) fresh
739798 let (propsToCheck, rest) = rowToList row
@@ -741,27 +800,24 @@ check' (ObjectUpdate obj ps) (Object row) = do
741800 remainingProps = filter (\(p, _) -> p `notElem` propsToRemove) propsToCheck
742801 obj' <- check obj (Object (rowFromList (us ++ remainingProps, rest)))
743802 ps' <- checkProperties ps row True
744− return $ ObjectUpdate obj' ps'
803+ return $ TypedValue True (ObjectUpdate obj' ps') t
745804check' (Accessor prop val) ty = do
746805 rest <- fresh
747806 val' <- check val (Object (RCons prop ty rest))
748− return $ Accessor prop val'
807+ return $ TypedValue True (Accessor prop val') ty
749808check' (Block ss) ret = do
750809 (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
751810 guardWith "Block is missing a return statement" allCodePathsReturn
752− return $ Block ss'
811+ return $ TypedValue True (Block ss') ret
753812check' (Constructor c) ty = do
754813 env <- getEnv
755814 Just moduleName <- checkCurrentModule <$> get
756815 case M.lookup (qualify moduleName c) (dataConstructors env) of
757816 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
758817 Just (ty1, _) -> do
759− repl <- replaceAllTypeSynonyms ty1
818+ repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
760819 _ <- subsumes Nothing repl ty
761− return $ Constructor c
762−check' val (SaturatedTypeSynonym name args) = do
763− ty <- expandTypeSynonym name args
764− check val ty
820+ return $ TypedValue True (Constructor c) ty
765821check' val ty = throwError $ prettyPrintValue val ++ " does not have type " ++ prettyPrintType ty
766822
767823-- |
@@ -774,7 +830,7 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
774830 go [] [] REmpty = return []
775831 go [] [] u@(TUnknown _) = do u =?= REmpty
776832 return []
777− go [] [] (Skolem _) | lax = return []
833+ go [] [] (Skolem _ _) | lax = return []
778834 go [] ((p, _): _) _ | lax = return []
779835 | otherwise = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have property " ++ p
780836 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
801857-- |
802858-- Check the type of a function application, rethrowing errors to provide a better error message
803859--
804−checkFunctionApplication :: Value -> Type -> Value -> Type -> UnifyT Type Check Value
805−checkFunctionApplication fn fnTy arg ret = rethrow errorMessage $ checkFunctionApplication' fn fnTy arg ret
860+checkFunctionApplication :: Value -> Type -> Value -> UnifyT Type Check (Type, Value)
861+checkFunctionApplication fn fnTy arg = rethrow errorMessage $ checkFunctionApplication' fn fnTy arg
806862 where
807863 errorMessage msg = "Error applying function of type "
808864 ++ prettyPrintType fnTy
@@ -812,34 +868,33 @@ checkFunctionApplication fn fnTy arg ret = rethrow errorMessage $ checkFunctionA
812868-- |
813869-- Check the type of a function application
814870--
815−checkFunctionApplication' :: Value -> Type -> Value -> Type -> UnifyT Type Check Value
816−checkFunctionApplication' fn (TypeApp (TypeApp tyFunction' argTy) retTy) arg ret = do
871+checkFunctionApplication' :: Value -> Type -> Value -> UnifyT Type Check (Type, Value)
872+checkFunctionApplication' fn (TypeApp (TypeApp tyFunction' argTy) retTy) arg = do
817873 tyFunction' =?= tyFunction
818874 arg' <- check arg argTy
819− _ <- subsumes Nothing retTy ret
820− return $ App fn arg'
821−checkFunctionApplication' fn (ForAll ident ty) arg ret = do
875+ return (retTy, App fn arg')
876+checkFunctionApplication' fn (ForAll ident ty _) arg = do
822877 replaced <- replaceVarWithUnknown ident ty
823− checkFunctionApplication fn replaced arg ret
824−checkFunctionApplication' fn u@(TUnknown _) arg ret = do
878+ checkFunctionApplication fn replaced arg
879+checkFunctionApplication' fn u@(TUnknown _) arg = do
825880 arg' <- do
826881 TypedValue _ v t <- infer arg
827882 TypedValue True v <$> replaceAllVarsWithUnknowns t
828883 let ty = (\(TypedValue _ _ t) -> t) arg'
884+ ret <- fresh
829885 u =?= function ty ret
830− return $ App fn arg'
831−checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do
832− ty <- expandTypeSynonym name tyArgs
833− checkFunctionApplication fn ty arg ret
834−checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
886+ return (ret, App fn arg')
887+checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg = do
888+ ty <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
889+ checkFunctionApplication fn ty arg
890+checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg = do
835891 env <- getEnv
836892 dicts <- getTypeClassDictionaries
837893 Just moduleName <- checkCurrentModule <$> get
838− checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) fnTy arg ret
839−checkFunctionApplication' _ fnTy arg ret = throwError $ "Applying a function of type "
894+ checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) fnTy arg
895+checkFunctionApplication' _ fnTy arg = throwError $ "Cannot apply a function of type "
840896 ++ prettyPrintType fnTy
841− ++ " to argument(s) " ++ prettyPrintValue arg
842− ++ " does not yield a value of type " ++ prettyPrintType ret ++ "."
897+ ++ " to argument " ++ prettyPrintValue arg
843898
844899-- |
845900-- 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
857912-- Check whether one type subsumes another
858913--
859914subsumes' :: 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
861916 replaced <- replaceVarWithUnknown ident ty1
862917 subsumes val replaced ty2
918+subsumes' val ty1 (ForAll ident ty2 sco) =
919+ case sco of
920+ Just sco' -> do
921+ sko <- newSkolemConstant
922+ let sk = skolemize ident sko sco' ty2
923+ subsumes val ty1 sk
924+ Nothing -> throwError "Skolem variable scope is unspecified"
863925subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do
864926 subsumes Nothing arg2 arg1
865927 subsumes Nothing ret1 ret2
866928 return val
867929subsumes' val (SaturatedTypeSynonym name tyArgs) ty2 = do
868− ty1 <- expandTypeSynonym name tyArgs
930+ ty1 <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
869931 subsumes val ty1 ty2
870932subsumes' val ty1 (SaturatedTypeSynonym name tyArgs) = do
871− ty2 <- expandTypeSynonym name tyArgs
933+ ty2 <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
872934 subsumes val ty1 ty2
873935subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
874936 env <- getEnv