@@ -14,6 +14,7 @@
1414-----------------------------------------------------------------------------
1515
1616{-# OPTIONS_GHC -fno-warn-orphans #-}
17+{-# LANGUAGE FlexibleInstances #-}
1718{-# LANGUAGE FlexibleContexts #-}
1819{-# LANGUAGE MultiParamTypeClasses #-}
1920
@@ -70,6 +71,7 @@ import Control.Arrow (Arrow(..))
7071import qualified Data.Map as M
7172import Data.Function (on)
7273import Data.Ord (comparing)
74+import Data.Monoid ((<>))
7375
7476instance Partial Type where
7577 unknown = TUnknown
@@ -83,7 +85,7 @@ instance Unifiable Check Type where
8385-- Unify two types, updating the current substitution
8486--
8587unifyTypes :: Type -> Type -> UnifyT Type Check ()
86−unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 ++ " with type " ++ prettyPrintType t2 ++ ":\n" ++ e) $
88+unifyTypes t1 t2 = rethrow (mkUnifyErrorStack ("Error unifying type " ++ prettyPrintType t1 ++ " with type " ++ prettyPrintType t2) Nothing <>) $
8789 unifyTypes' t1 t2
8890 where
8991 unifyTypes' (TUnknown u1) (TUnknown u2) | u1 == u2 = return ()
@@ -100,16 +102,16 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
100102 let sk1 = skolemize ident1 sko sc1' ty1
101103 let sk2 = skolemize ident2 sko sc2' ty2
102104 sk1 `unifyTypes` sk2
103− _ -> throwError (prettyPrintType ty1)
105+ _ -> error "Skolemized type variable was not given a scope"
104106 unifyTypes' (ForAll ident ty1 (Just sc)) ty2 = do
105107 sko <- newSkolemConstant
106108 let sk = skolemize ident sko sc ty1
107109 sk `unifyTypes` ty2
108− unifyTypes' ForAll{} _ = throwError "Skolem variable scope is unspecified"
110+ unifyTypes' ForAll{} _ = throwError . strMsg $ "Skolem variable scope is unspecified"
109111 unifyTypes' ty f@ForAll{} = f `unifyTypes` ty
110112 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
111113 unifyTypes' (TypeConstructor c1) (TypeConstructor c2) =
112− guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (c1 == c2)
114+ guardWith (strMsg ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".")) (c1 == c2)
113115 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
114116 t3 `unifyTypes` t5
115117 t4 `unifyTypes` t6
@@ -118,10 +120,9 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
118120 unifyTypes' r1 r2@RCons{} = unifyRows r1 r2
119121 unifyTypes' r1@REmpty r2 = unifyRows r1 r2
120122 unifyTypes' r1 r2@REmpty = unifyRows r1 r2
121− unifyTypes' t@(ConstrainedType _ _) _ = throwError $ "Attempted to unify a constrained type " ++ prettyPrintType t ++
122− " with another type."
123+ unifyTypes' t@(ConstrainedType _ _) _ = throwError . strMsg $ "Attempted to unify a constrained type " ++ prettyPrintType t ++ " with another type."
123124 unifyTypes' t3 t4@(ConstrainedType _ _) = unifyTypes' t4 t3
124− unifyTypes' t3 t4 = throwError $ "Cannot unify " ++ prettyPrintType t3 ++ " with " ++ prettyPrintType t4 ++ "."
125+ unifyTypes' t3 t4 = throwError . strMsg $ "Cannot unify " ++ prettyPrintType t3 ++ " with " ++ prettyPrintType t4 ++ "."
125126
126127-- |
127128-- Unify two rows, updating the current substitution
@@ -154,7 +155,7 @@ unifyRows r1 r2 =
154155 unifyRows' [] REmpty [] REmpty = return ()
155156 unifyRows' [] (TypeVar v1) [] (TypeVar v2) | v1 == v2 = return ()
156157 unifyRows' [] (Skolem s1 _) [] (Skolem s2 _) | s1 == s2 = return ()
157− unifyRows' sd3 r3 sd4 r4 = throwError $ "Cannot unify (" ++ prettyPrintRow (rowFromList (sd3, r3)) ++ ") with (" ++ prettyPrintRow (rowFromList (sd4, r4)) ++ ")."
158+ unifyRows' sd3 r3 sd4 r4 = throwError . strMsg $ "Cannot unify (" ++ prettyPrintRow (rowFromList (sd3, r3)) ++ ") with (" ++ prettyPrintRow (rowFromList (sd4, r4)) ++ ")"
158159
159160-- |
160161-- Infer the types of multiple mutually-recursive values, and return elaborated values including
@@ -217,7 +218,7 @@ typeForBindingGroupElement moduleName e@(_, (val, _)) dict untypedDict = do
217218 (ident, (val', Just (ty, checkType))) -> do
218219 -- Kind check
219220 kind <- liftCheck $ kindOf moduleName ty
220− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
221+ guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
221222 -- Check the type with the new names in scope
222223 ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
223224 val'' <- bindNames dict' $ if checkType
@@ -270,7 +271,7 @@ replaceTypeClassDictionaries mn = everywhereM' (mkM go)
270271entails :: Environment -> ModuleName -> [TypeClassDictionaryInScope] -> (Qualified ProperName, [Type]) -> Check Value
271272entails env moduleName context goal@(className, tys) = do
272273 case go goal of
273− [] -> throwError $ "No " ++ show className ++ " instance found for " ++ intercalate ", " (map prettyPrintType tys)
274+ [] -> throwError . strMsg $ "No " ++ show className ++ " instance found for " ++ intercalate ", " (map prettyPrintType tys)
274275 (dict : _) -> return dict
275276 where
276277 go (className', tys') =
@@ -362,7 +363,7 @@ skolemEscapeCheck root@TypedValue{} =
362363 -- an escaped skolem variable.
363364 case everythingWithContext [] (++) (mkQ ((,) []) go) root of
364365 [] -> return ()
365− ((binding, val) : _) -> throwError $ "Rigid/skolem type variable bound by " ++ maybe "<unknown>" prettyPrintValue binding ++ " has escaped at " ++ prettyPrintValue val
366+ ((binding, val) : _) -> throwError $ mkUnifyErrorStack ("Rigid/skolem type variable " ++ maybe "" (("bound by " ++) . prettyPrintValue) binding ++ " has escaped.") (Just (ValueError val))
366367 where
367368 go :: Value -> [(SkolemScope, Value)] -> ([(Maybe Value, Value)], [(SkolemScope, Value)])
368369 go val@(TypedValue _ _ (ForAll _ _ (Just sco))) scos = ([], (sco, val) : scos)
@@ -381,7 +382,7 @@ skolemEscapeCheck root@TypedValue{} =
381382 where
382383 go' val@(TypedValue _ _ (ForAll _ _ (Just sco'))) | sco == sco' = Just val
383384 go' _ = Nothing
384−skolemEscapeCheck val = throwError $ "Untyped value passed to skolemEscapeCheck: " ++ prettyPrintValue val
385+skolemEscapeCheck val = throwError $ mkUnifyErrorStack "Untyped value passed to skolemEscapeCheck" (Just (ValueError val))
385386
386387-- |
387388-- Ensure a row contains no duplicate labels
@@ -444,10 +445,10 @@ replaceAllTypeSynonyms' env d =
444445 in
445446 saturateAllTypeSynonyms syns d
446447
447−replaceAllTypeSynonyms :: (Functor m, Monad m, MonadState CheckState m, MonadError String m) => (D.Data d) => d -> m d
448+replaceAllTypeSynonyms :: (Error e, Functor m, Monad m, MonadState CheckState m, MonadError e m) => (D.Data d) => d -> m d
448449replaceAllTypeSynonyms d = do
449450 env <- getEnv
450− either throwError return $ replaceAllTypeSynonyms' env d
451+ either (throwError . strMsg) return $ replaceAllTypeSynonyms' env d
451452
452453-- |
453454-- \"Desaturate\" @SaturatedTypeSynonym@s
@@ -469,12 +470,12 @@ expandTypeSynonym' env name args =
469470 replaceAllTypeSynonyms' env repl
470471 Nothing -> error "Type synonym was not defined"
471472
472−expandTypeSynonym :: (Functor m, Monad m, MonadState CheckState m, MonadError String m) => Qualified ProperName -> [Type] -> m Type
473+expandTypeSynonym :: (Error e, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Qualified ProperName -> [Type] -> m Type
473474expandTypeSynonym name args = do
474475 env <- getEnv
475− either throwError return $ expandTypeSynonym' env name args
476+ either (throwError . strMsg) return $ expandTypeSynonym' env name args
476477
477−expandAllTypeSynonyms :: (Functor m, Monad m, MonadState CheckState m, MonadError String m) => Type -> m Type
478+expandAllTypeSynonyms :: (Error e, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
478479expandAllTypeSynonyms = everywhereM' (mkM go)
479480 where
480481 go (SaturatedTypeSynonym name args) = expandTypeSynonym name args
@@ -483,14 +484,14 @@ expandAllTypeSynonyms = everywhereM' (mkM go)
483484-- |
484485-- Ensure a set of property names and value does not contain duplicate labels
485486--
486−ensureNoDuplicateProperties :: (MonadError String m) => [(String, Value)] -> m ()
487−ensureNoDuplicateProperties ps = guardWith "Duplicate property names" $ length (nub . map fst $ ps) == length ps
487+ensureNoDuplicateProperties :: (Error e, MonadError e m) => [(String, Value)] -> m ()
488+ensureNoDuplicateProperties ps = guardWith (strMsg "Duplicate property names") $ length (nub . map fst $ ps) == length ps
488489
489490-- |
490491-- Infer a type for a value, rethrowing any error to provide a more useful error message
491492--
492493infer :: Value -> UnifyT Type Check Value
493−infer val = rethrow (\e -> "Error inferring type of term " ++ prettyPrintValue val ++ ":\n" ++ e) $ infer' val
494+infer val = rethrow (mkUnifyErrorStack "Error inferring type of value" (Just (ValueError val)) <>) $ infer' val
494495
495496-- |
496497-- Infer a type for a value
@@ -551,7 +552,7 @@ infer' (Var var) = do
551552infer' v@(Constructor c) = do
552553 env <- getEnv
553554 case M.lookup c (dataConstructors env) of
554− Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
555+ Nothing -> throwError . strMsg $ "Constructor " ++ show c ++ " is undefined"
555556 Just (_, ty) -> do ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
556557 return $ TypedValue True v ty'
557558infer' (Case vals binders) = do
@@ -571,7 +572,7 @@ infer' (Let ds val) = do
571572infer' (TypedValue checkType val ty) = do
572573 Just moduleName <- checkCurrentModule <$> get
573574 kind <- liftCheck $ kindOf moduleName ty
574− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
575+ guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
575576 ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
576577 val' <- if checkType then check val ty' else return val
577578 return $ TypedValue True val' ty'
@@ -631,8 +632,8 @@ inferBinder val (ConstructorBinder ctor binders) = do
631632 return M.empty
632633 go (binder : binders') (TypeApp (TypeApp t obj) ret) | t == tyFunction =
633634 M.union <$> inferBinder obj binder <*> go binders' ret
634− go _ _ = throwError $ "Wrong number of arguments to constructor " ++ show ctor
635− _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
635+ go _ _ = throwError . strMsg $ "Wrong number of arguments to constructor " ++ show ctor
636+ _ -> throwError . strMsg $ "Constructor " ++ show ctor ++ " is not defined"
636637inferBinder val (ObjectBinder props) = do
637638 row <- fresh
638639 rest <- fresh
@@ -711,15 +712,13 @@ introduceSkolemScope = everywhereM (mkM go)
711712-- Check the type of a value, rethrowing errors to provide a better error message
712713--
713714check :: Value -> Type -> UnifyT Type Check Value
714−check val ty = rethrow errorMessage $ check' val ty
715+check val ty = rethrow (mkUnifyErrorStack errorMessage (Just (ValueError val)) <>) $ check' val ty
715716 where
716− errorMessage msg =
717+ errorMessage =
717718 "Error checking type of term " ++
718719 prettyPrintValue val ++
719720 " against type " ++
720− prettyPrintType ty ++
721− ":\n" ++
722− msg
721+ prettyPrintType ty
723722
724723-- |
725724-- Check the type of a value
@@ -773,16 +772,16 @@ check' v@(Var var) ty = do
773772 ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
774773 v' <- subsumes (Just v) repl ty'
775774 case v' of
776− Nothing -> throwError "Unable to check type subsumption"
775+ Nothing -> throwError . strMsg $ "Unable to check type subsumption"
777776 Just v'' -> return $ TypedValue True v'' ty'
778777check' (TypedValue checkType val ty1) ty2 = do
779778 Just moduleName <- checkCurrentModule <$> get
780779 kind <- liftCheck $ kindOf moduleName ty1
781− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
780+ guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
782781 ty1' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
783782 val' <- subsumes (Just val) ty1' ty2
784783 case val' of
785− Nothing -> throwError "Unable to check type subsumption"
784+ Nothing -> throwError . strMsg $ "Unable to check type subsumption"
786785 Just val'' -> do
787786 val''' <- if checkType then check val'' ty1' else return val''
788787 return $ TypedValue checkType (TypedValue True val''' ty1) ty2
@@ -816,7 +815,7 @@ check' (Accessor prop val) ty = do
816815check' (Constructor c) ty = do
817816 env <- getEnv
818817 case M.lookup c (dataConstructors env) of
819− Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
818+ Nothing -> throwError . strMsg $ "Constructor " ++ show c ++ " is undefined"
820819 Just (_, ty1) -> do
821820 repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
822821 _ <- subsumes Nothing repl ty
@@ -827,7 +826,7 @@ check' (Let ds val) ty = do
827826check' val ty | containsTypeSynonyms ty = do
828827 ty' <- introduceSkolemScope <=< expandAllTypeSynonyms $ ty
829828 check val ty'
830−check' val ty = throwError $ prettyPrintValue val ++ " does not have type " ++ prettyPrintType ty
829+check' val ty = throwError $ mkUnifyErrorStack ("Value does not have type " ++ prettyPrintType ty) (Just (ValueError val))
831830
832831containsTypeSynonyms :: Type -> Bool
833832containsTypeSynonyms = everything (||) (mkQ False go) where
@@ -846,8 +845,8 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
846845 return []
847846 go [] [] (Skolem _ _) | lax = return []
848847 go [] ((p, _): _) _ | lax = return []
849− | otherwise = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have property " ++ p
850− go ((p,_):_) [] REmpty = throwError $ "Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row
848+ | otherwise = throwError $ mkUnifyErrorStack ("Object does not have property " ++ p) (Just (ValueError (ObjectLiteral ps)))
849+ go ((p,_):_) [] REmpty = throwError $ mkUnifyErrorStack ("Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row) (Just (ValueError (ObjectLiteral ps)))
851850 go ((p,v):ps') [] u@(TUnknown _) = do
852851 v'@(TypedValue _ _ ty) <- infer v
853852 rest <- fresh
@@ -866,18 +865,17 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
866865 v' <- check v ty
867866 ps'' <- go ps' (delete (p, ty) ts) r
868867 return $ (p, v') : ps''
869− go _ _ _ = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have type " ++ prettyPrintType (TypeApp tyObject row)
868+ go _ _ _ = throwError $ mkUnifyErrorStack ("Object does not have type " ++ prettyPrintType (TypeApp tyObject row)) (Just (ValueError (ObjectLiteral ps)))
870869
871870-- |
872871-- Check the type of a function application, rethrowing errors to provide a better error message
873872--
874873checkFunctionApplication :: Value -> Type -> Value -> Maybe Type -> UnifyT Type Check (Type, Value)
875−checkFunctionApplication fn fnTy arg ret = rethrow errorMessage $ checkFunctionApplication' fn fnTy arg ret
874+checkFunctionApplication fn fnTy arg ret = rethrow (mkUnifyErrorStack errorMessage (Just (ValueError fn)) <>) $ checkFunctionApplication' fn fnTy arg ret
876875 where
877− errorMessage msg = "Error applying function of type "
876+ errorMessage = "Error applying function of type "
878877 ++ prettyPrintType fnTy
879878 ++ " to argument " ++ prettyPrintValue arg
880− ++ ":\n" ++ msg
881879
882880-- |
883881-- Check the type of a function application
@@ -907,7 +905,7 @@ checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do
907905checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
908906 dicts <- getTypeClassDictionaries
909907 checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) constraints)) fnTy arg ret
910−checkFunctionApplication' _ fnTy arg _ = throwError $ "Cannot apply a function of type "
908+checkFunctionApplication' _ fnTy arg _ = throwError . strMsg $ "Cannot apply a function of type "
911909 ++ prettyPrintType fnTy
912910 ++ " to argument " ++ prettyPrintValue arg
913911
@@ -915,13 +913,12 @@ checkFunctionApplication' _ fnTy arg _ = throwError $ "Cannot apply a function o
915913-- Check whether one type subsumes another, rethrowing errors to provide a better error message
916914--
917915subsumes :: Maybe Value -> Type -> Type -> UnifyT Type Check (Maybe Value)
918−subsumes val ty1 ty2 = rethrow errorMessage $ subsumes' val ty1 ty2
916+subsumes val ty1 ty2 = rethrow (mkUnifyErrorStack errorMessage (ValueError <$> val) <>) $ subsumes' val ty1 ty2
919917 where
920− errorMessage msg = "Error checking that type "
918+ errorMessage = "Error checking that type "
921919 ++ prettyPrintType ty1
922920 ++ " subsumes type "
923921 ++ prettyPrintType ty2
924− ++ ":\n" ++ msg
925922
926923-- |
927924-- Check whether one type subsumes another
@@ -936,7 +933,7 @@ subsumes' val ty1 (ForAll ident ty2 sco) =
936933 sko <- newSkolemConstant
937934 let sk = skolemize ident sko sco' ty2
938935 subsumes val ty1 sk
939− Nothing -> throwError "Skolem variable scope is unspecified"
936+ Nothing -> throwError . strMsg $ "Skolem variable scope is unspecified"
940937subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do
941938 _ <- subsumes Nothing arg2 arg1
942939 _ <- subsumes Nothing ret1 ret2
@@ -976,3 +973,4 @@ subsumes' val ty1 ty2 = do
976973 ty1 =?= ty2
977974 return val
978975
976+