@@ -263,8 +263,7 @@ replaceTypeClassDictionaries mn = everywhereM' (mkM go)
264 go (TypeClassDictionary trySuperclasses constraint dicts) = do
264 go (TypeClassDictionary trySuperclasses constraint dicts) = do
265 env <- getEnv
265 env <- getEnv
266− let dicts' = fromMaybe (typeClassDictionaries env) dicts
267− entails env mn dicts' constraint trySuperclasses
266+ entails env mn dicts constraint trySuperclasses
268 go other = return other
267 go other = return other
@@ -287,7 +286,7 @@ data DictionaryValue
288 -- A subclass dictionary
287 -- A subclass dictionary
290− | SubclassDictionaryValue DictionaryValue Integer
289+ | SubclassDictionaryValue DictionaryValue (Qualified ProperName) Integer
291 deriving (Show, Ord, Eq)
290 deriving (Show, Ord, Eq)
@@ -307,12 +306,12 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
307 filterModule _ = False
306 filterModule _ = False
309 solve context' (className, tys) trySuperclasses =
308 solve context' (className, tys) trySuperclasses =
310− case chooseSimplestDictionaries (go className tys) of
309+ case chooseSimplestDictionaries (go trySuperclasses className tys) of
311 [] -> throwError . strMsg $ "No instance found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
310 [] -> throwError . strMsg $ "No instance found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
312 [dict] -> return (dictionaryValueToValue dict)
311 [dict] -> return (dictionaryValueToValue dict)
313 _ -> throwError . strMsg $ "Overlapping instances found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
312 _ -> throwError . strMsg $ "Overlapping instances found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
315− go className' tys' =
314+ go trySuperclasses' className' tys' =
316 -- Look for regular type instances
315 -- Look for regular type instances
317 [ mkDictionary (canonicalizeDictionary tcd) args
316 [ mkDictionary (canonicalizeDictionary tcd) args
318 | tcd <- context'
317 | tcd <- context'
@@ -324,8 +323,8 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
324 , args <- solveSubgoals subst (tcdDependencies tcd) ] ++
323 , args <- solveSubgoals subst (tcdDependencies tcd) ] ++
326 -- Look for implementations via superclasses
325 -- Look for implementations via superclasses
327− [ SubclassDictionaryValue suDict index
326+ [ SubclassDictionaryValue suDict superclass index
328− | trySuperclasses
327+ | trySuperclasses'
329 , (subclassName, (args, _, implies)) <- M.toList (typeClasses env)
328 , (subclassName, (args, _, implies)) <- M.toList (typeClasses env)
330 -- Try each superclass
329 -- Try each superclass
331 , (index, (superclass, suTyArgs)) <- zip [0..] implies
330 , (index, (superclass, suTyArgs)) <- zip [0..] implies
@@ -334,7 +333,7 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
334 -- Make sure the types unify with the types in the superclass implication
333 -- Make sure the types unify with the types in the superclass implication
335 , subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' suTyArgs
334 , subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' suTyArgs
336 -- Finally, satisfy the subclass constraint
335 -- Finally, satisfy the subclass constraint
337− , suDict <- go subclassName (map (applySubst subst . TypeVar) args) ]
336+ , suDict <- go trySuperclasses' subclassName (map (applySubst subst . TypeVar) args) ]
339 -- Create dictionaries for subgoals which still need to be solved by calling go recursively
338 -- Create dictionaries for subgoals which still need to be solved by calling go recursively
340 -- E.g. the goal (Show a, Show b) => Show (Either a b) can be satisfied if the current type
339 -- E.g. the goal (Show a, Show b) => Show (Either a b) can be satisfied if the current type
@@ -342,7 +341,7 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
342 solveSubgoals :: [(String, Type)] -> Maybe [(Qualified ProperName, [Type])] -> [Maybe [DictionaryValue]]
341 solveSubgoals :: [(String, Type)] -> Maybe [(Qualified ProperName, [Type])] -> [Maybe [DictionaryValue]]
343 solveSubgoals _ Nothing = return Nothing
342 solveSubgoals _ Nothing = return Nothing
344 solveSubgoals subst (Just subgoals) = do
343 solveSubgoals subst (Just subgoals) = do
345− dict <- mapM (uncurry go . second (map (replaceAllTypeVars subst))) subgoals
344+ dict <- mapM (uncurry (go True) . second (map (replaceAllTypeVars subst))) subgoals
346 return $ Just dict
345 return $ Just dict
347 -- Make a dictionary from subgoal dictionaries by applying the correct function
346 -- Make a dictionary from subgoal dictionaries by applying the correct function
348 mkDictionary :: Qualified Ident -> Maybe [DictionaryValue] -> DictionaryValue
347 mkDictionary :: Qualified Ident -> Maybe [DictionaryValue] -> DictionaryValue
@@ -354,10 +353,9 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
354 dictionaryValueToValue (LocalDictionaryValue fnName) = Var fnName
353 dictionaryValueToValue (LocalDictionaryValue fnName) = Var fnName
355 dictionaryValueToValue (GlobalDictionaryValue fnName) = App (Var fnName) (ObjectLiteral [])
354 dictionaryValueToValue (GlobalDictionaryValue fnName) = App (Var fnName) (ObjectLiteral [])
356 dictionaryValueToValue (DependentDictionaryValue fnName dicts) = foldl App (Var fnName) (map dictionaryValueToValue dicts)
355 dictionaryValueToValue (DependentDictionaryValue fnName dicts) = foldl App (Var fnName) (map dictionaryValueToValue dicts)
357− dictionaryValueToValue (SubclassDictionaryValue dict index) =
356+ dictionaryValueToValue (SubclassDictionaryValue dict superclassName index) =
358− App (App (App (Var (Qualified (Just (ModuleName [ProperName C.prelude])) (Ident (C.!!))))
357+ App (Accessor (show superclassName ++ "_" ++ show index)
359 (Accessor C.__superclasses (dictionaryValueToValue dict)))
358 (Accessor C.__superclasses (dictionaryValueToValue dict)))
360− (NumericLiteral (Left index)))
361 (ObjectLiteral [])
359 (ObjectLiteral [])
362 -- Ensure that a substitution is valid
360 -- Ensure that a substitution is valid
363 verifySubstitution :: [(String, Type)] -> Maybe [(String, Type)]
361 verifySubstitution :: [(String, Type)] -> Maybe [(String, Type)]
@@ -500,7 +498,7 @@ instantiatePolyTypeWithUnknowns val (ForAll ident ty _) = do
500instantiatePolyTypeWithUnknowns val (ConstrainedType constraints ty) = do
498instantiatePolyTypeWithUnknowns val (ConstrainedType constraints ty) = do
501 dicts <- getTypeClassDictionaries
499 dicts <- getTypeClassDictionaries
502 (_, ty') <- instantiatePolyTypeWithUnknowns (error "Types under a constraint cannot themselves be constrained") ty
500 (_, ty') <- instantiatePolyTypeWithUnknowns (error "Types under a constraint cannot themselves be constrained") ty
503− return (foldl App val (map (flip (TypeClassDictionary True) (Just dicts)) constraints), ty')
501+ return (foldl App val (map (flip (TypeClassDictionary True) dicts) constraints), ty')
504instantiatePolyTypeWithUnknowns val ty = return (val, ty)
502instantiatePolyTypeWithUnknowns val ty = return (val, ty)
@@ -624,7 +622,7 @@ infer' (Var var) = do
624 case ty of
622 case ty of
625 ConstrainedType constraints ty' -> do
623 ConstrainedType constraints ty' -> do
626 dicts <- getTypeClassDictionaries
624 dicts <- getTypeClassDictionaries
627− return $ TypedValue True (foldl App (Var var) (map (flip (TypeClassDictionary True) (Just dicts)) constraints)) ty'
625+ return $ TypedValue True (foldl App (Var var) (map (flip (TypeClassDictionary True) dicts) constraints)) ty'
628 _ -> return $ TypedValue True (Var var) ty
626 _ -> return $ TypedValue True (Var var) ty
629infer' v@(Constructor c) = do
627infer' v@(Constructor c) = do
630 env <- getEnv
628 env <- getEnv
@@ -646,6 +644,9 @@ infer' (IfThenElse cond th el) = do
646infer' (Let ds val) = do
644infer' (Let ds val) = do
647 (ds', val'@(TypedValue _ _ valTy)) <- inferLetBinding [] ds val infer
645 (ds', val'@(TypedValue _ _ valTy)) <- inferLetBinding [] ds val infer
648 return $ TypedValue True (Let ds' val') valTy
646 return $ TypedValue True (Let ds' val') valTy
647+infer' (SuperClassDictionary className tys) = do
648+ dicts <- getTypeClassDictionaries
649+ return $ TypeClassDictionary False (className, tys) dicts
649infer' (TypedValue checkType val ty) = do
650infer' (TypedValue checkType val ty) = do
650 Just moduleName <- checkCurrentModule <$> get
651 Just moduleName <- checkCurrentModule <$> get
651 kind <- liftCheck $ kindOf moduleName ty
652 kind <- liftCheck $ kindOf moduleName ty
@@ -783,6 +784,17 @@ newSkolemScope = SkolemScope . runUnknown <$> fresh'
783skolemize :: String -> Int -> SkolemScope -> Type -> Type
784skolemize :: String -> Int -> SkolemScope -> Type -> Type
784skolemize ident sko scope = replaceTypeVars ident (Skolem sko scope)
785skolemize ident sko scope = replaceTypeVars ident (Skolem sko scope)
788+-- This function has one purpose - to skolemize type variables appearing in a
789+-- SuperClassDictionary placeholder. These type variables are somewhat unique since they are the
790+-- only example of scoped type variables.
792+skolemizeTypesInValue :: String -> Int -> SkolemScope -> Value -> Value
793+skolemizeTypesInValue ident sko scope = everywhere (mkT go)
795+ go (SuperClassDictionary c ts) = SuperClassDictionary c (map (skolemize ident sko scope) ts)
787-- Introduce skolem scope at every occurence of a ForAll
799-- Introduce skolem scope at every occurence of a ForAll
@@ -812,7 +824,8 @@ check' val (ForAll ident ty _) = do
812 scope <- newSkolemScope
824 scope <- newSkolemScope
813 sko <- newSkolemConstant
825 sko <- newSkolemConstant
814 let sk = skolemize ident sko scope ty
826 let sk = skolemize ident sko scope ty
827+ let skVal = skolemizeTypesInValue ident sko scope val
815− val' <- check val sk
828+ val' <- check skVal sk
816 return $ TypedValue True val' (ForAll ident ty (Just scope))
829 return $ TypedValue True val' (ForAll ident ty (Just scope))
817check' val t@(ConstrainedType constraints ty) = do
830check' val t@(ConstrainedType constraints ty) = do
818 dictNames <- forM constraints $ \(Qualified _ (ProperName className), _) -> do
831 dictNames <- forM constraints $ \(Qualified _ (ProperName className), _) -> do
@@ -858,6 +871,19 @@ check' v@(Var var) ty = do
858 case v' of
871 case v' of
859 Nothing -> throwError . strMsg $ "Unable to check type subsumption"
872 Nothing -> throwError . strMsg $ "Unable to check type subsumption"
860 Just v'' -> return $ TypedValue True v'' ty'
873 Just v'' -> return $ TypedValue True v'' ty'
874+check' (SuperClassDictionary className tys) _ = do
876+ -- Here, we replace a placeholder for a superclass dictionary with a regular
877+ -- TypeClassDictionary placeholder. The reason we do this is that it is necessary to have the
878+ -- correct super instance dictionaries in scope, and these are not available when the type class
879+ -- declaration gets desugared.
881+ -- Note also that the first argument to TypeClassDictionary is False, meaning we _do not_ want
882+ -- to consider superclass instances when searching for this dictionary - doing so might lead
883+ -- to traversing a cycle in the instance graph.
885+ dicts <- getTypeClassDictionaries
886+ return $ TypeClassDictionary False (className, tys) dicts
861check' (TypedValue checkType val ty1) ty2 = do
887check' (TypedValue checkType val ty1) ty2 = do
862 Just moduleName <- checkCurrentModule <$> get
888 Just moduleName <- checkCurrentModule <$> get
863 kind <- liftCheck $ kindOf moduleName ty1
889 kind <- liftCheck $ kindOf moduleName ty1
@@ -990,7 +1016,7 @@ checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do
990 checkFunctionApplication fn ty arg ret
1016 checkFunctionApplication fn ty arg ret
991checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
1017checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
992 dicts <- getTypeClassDictionaries
1018 dicts <- getTypeClassDictionaries
993− checkFunctionApplication' (foldl App fn (map (flip (TypeClassDictionary True) (Just dicts)) constraints)) fnTy arg ret
1019+ checkFunctionApplication' (foldl App fn (map (flip (TypeClassDictionary True) dicts) constraints)) fnTy arg ret
994checkFunctionApplication' _ fnTy arg _ = throwError . strMsg $ "Cannot apply a function of type "
1020checkFunctionApplication' _ fnTy arg _ = throwError . strMsg $ "Cannot apply a function of type "
995 ++ prettyPrintType fnTy
1021 ++ prettyPrintType fnTy
996 ++ " to argument " ++ prettyPrintValue arg
1022 ++ " to argument " ++ prettyPrintValue arg
@@ -1033,7 +1059,7 @@ subsumes' val ty1 (SaturatedTypeSynonym name tyArgs) = do
1033subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
1059subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
1034 dicts <- getTypeClassDictionaries
1060 dicts <- getTypeClassDictionaries
1035 _ <- subsumes' Nothing ty1 ty2
1061 _ <- subsumes' Nothing ty1 ty2
1036− return . Just $ foldl App val (map (flip (TypeClassDictionary True) (Just dicts)) constraints)
1062+ return . Just $ foldl App val (map (flip (TypeClassDictionary True) dicts) constraints)
1037subsumes' val (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyObject && f2 == tyObject = do
1063subsumes' val (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyObject && f2 == tyObject = do
1039 (ts1, r1') = rowToList r1
1065 (ts1, r1') = rowToList r1