@@ -116,7 +116,7 @@ unifyTypes t1 t2 = rethrow (mkErrorStack ("Error unifying type " ++ prettyPrintT
116116 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
117117 t3 `unifyTypes` t5
118118 t4 `unifyTypes` t6
119− unifyTypes' (Skolem s1 _) (Skolem s2 _) | s1 == s2 = return ()
119+ unifyTypes' (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = return ()
120120 unifyTypes' r1@RCons{} r2 = unifyRows r1 r2
121121 unifyTypes' r1 r2@RCons{} = unifyRows r1 r2
122122 unifyTypes' r1@REmpty r2 = unifyRows r1 r2
@@ -155,7 +155,7 @@ unifyRows r1 r2 =
155155 unifyRows' row r others u'
156156 unifyRows' [] REmpty [] REmpty = return ()
157157 unifyRows' [] (TypeVar v1) [] (TypeVar v2) | v1 == v2 = return ()
158− unifyRows' [] (Skolem s1 _) [] (Skolem s2 _) | s1 == s2 = return ()
158+ unifyRows' [] (Skolem _ s1 _) [] (Skolem _ s2 _) | s1 == s2 = return ()
159159 unifyRows' sd3 r3 sd4 r4 = throwError . strMsg $ "Cannot unify (" ++ prettyPrintRow (rowFromList (sd3, r3)) ++ ") with (" ++ prettyPrintRow (rowFromList (sd4, r4)) ++ ")"
160160
161161-- |
@@ -261,9 +261,9 @@ overTypes f = everywhere (mkT f)
261261replaceTypeClassDictionaries :: ModuleName -> Value -> Check Value
262262replaceTypeClassDictionaries mn = everywhereM' (mkM go)
263263 where
264− go (TypeClassDictionary constraint dicts) = do
264+ go (TypeClassDictionary trySuperclasses constraint dicts) = do
265265 env <- getEnv
266− entails env mn dicts constraint
266+ entails env mn dicts constraint trySuperclasses
267267 go other = return other
268268
269269-- |
@@ -283,13 +283,17 @@ data DictionaryValue
283283 -- A dictionary which depends on other dictionaries
284284 --
285285 | DependentDictionaryValue (Qualified Ident) [DictionaryValue]
286+ -- |
287+ -- A subclass dictionary
288+ --
289+ | SubclassDictionaryValue DictionaryValue (Qualified ProperName) Integer
286290 deriving (Show, Ord, Eq)
287291
288292-- |
289293-- Check that the current set of type class dictionaries entail the specified type class goal, and, if so,
290294-- return a type class dictionary reference.
291295--
292−entails :: Environment -> ModuleName -> [TypeClassDictionaryInScope] -> (Qualified ProperName, [Type]) -> Check Value
296+entails :: Environment -> ModuleName -> [TypeClassDictionaryInScope] -> (Qualified ProperName, [Type]) -> Bool -> Check Value
293297entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filter filterModule context))
294298 where
295299 sortedNubBy :: (Ord k) => (v -> k) -> [v] -> [v]
@@ -301,13 +305,16 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
301305 filterModule (TypeClassDictionaryInScope { tcdName = Qualified Nothing _ }) = True
302306 filterModule _ = False
303307
304− solve context' goal@(className, tys) =
305− case go goal of
306− [] -> throwError . strMsg $ "No instance found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
307− [dict] -> return (dictionaryValueToValue dict)
308− _ -> throwError . strMsg $ "Overlapping instances found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
308+ solve context' (className, tys) trySuperclasses =
309+ let
310+ dicts = go trySuperclasses className tys
311+ in case sortedNubBy dictTrace (chooseSimplestDictionaries dicts) of
312+ [] -> throwError . strMsg $ "No instance found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
313+ [_] -> return $ dictionaryValueToValue $ head dicts
314+ _ -> throwError . strMsg $ "Overlapping instances found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
309315 where
310− go (className', tys') =
316+ go trySuperclasses' className' tys' =
317+ -- Look for regular type instances
311318 [ mkDictionary (canonicalizeDictionary tcd) args
312319 | tcd <- context'
313320 -- Make sure the type class name matches the one we are trying to satisfy
@@ -315,14 +322,29 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
315322 -- Make sure the type unifies with the type in the type instance definition
316323 , subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' (tcdInstanceTypes tcd)
317324 -- Solve any necessary subgoals
318− , args <- solveSubgoals subst (tcdDependencies tcd) ]
325+ , args <- solveSubgoals subst (tcdDependencies tcd) ] ++
326+
327+ -- Look for implementations via superclasses
328+ [ SubclassDictionaryValue suDict superclass index
329+ | trySuperclasses'
330+ , (subclassName, (args, _, implies)) <- M.toList (typeClasses env)
331+ -- Try each superclass
332+ , (index, (superclass, suTyArgs)) <- zip [0..] implies
333+ -- Make sure the type class name matches the superclass name
334+ , className' == superclass
335+ -- Make sure the types unify with the types in the superclass implication
336+ , subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' suTyArgs
337+ -- Finally, satisfy the subclass constraint
338+ , args' <- maybeToList $ mapM (applySubst subst . TypeVar) args
339+ , suDict <- go True subclassName args' ]
340+
319341 -- Create dictionaries for subgoals which still need to be solved by calling go recursively
320342 -- E.g. the goal (Show a, Show b) => Show (Either a b) can be satisfied if the current type
321343 -- unifies with Either a b, and we can satisfy the subgoals Show a and Show b recursively.
322344 solveSubgoals :: [(String, Type)] -> Maybe [(Qualified ProperName, [Type])] -> [Maybe [DictionaryValue]]
323345 solveSubgoals _ Nothing = return Nothing
324346 solveSubgoals subst (Just subgoals) = do
325− dict <- mapM (go . second (map (replaceAllTypeVars subst))) subgoals
347+ dict <- mapM (uncurry (go True) . second (map (replaceAllTypeVars subst))) subgoals
326348 return $ Just dict
327349 -- Make a dictionary from subgoal dictionaries by applying the correct function
328350 mkDictionary :: Qualified Ident -> Maybe [DictionaryValue] -> DictionaryValue
@@ -334,12 +356,45 @@ entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filt
334356 dictionaryValueToValue (LocalDictionaryValue fnName) = Var fnName
335357 dictionaryValueToValue (GlobalDictionaryValue fnName) = App (Var fnName) (ObjectLiteral [])
336358 dictionaryValueToValue (DependentDictionaryValue fnName dicts) = foldl App (Var fnName) (map dictionaryValueToValue dicts)
359+ dictionaryValueToValue (SubclassDictionaryValue dict superclassName index) =
360+ App (Accessor (show superclassName ++ "_" ++ show index)
361+ (Accessor C.__superclasses (dictionaryValueToValue dict)))
362+ (ObjectLiteral [])
337363 -- Ensure that a substitution is valid
338364 verifySubstitution :: [(String, Type)] -> Maybe [(String, Type)]
339365 verifySubstitution subst = do
340366 let grps = groupBy ((==) `on` fst) subst
341367 guard (all (pairwise (unifiesWith env) . map snd) grps)
342368 return $ map head grps
369+ -- Apply a substitution to a type
370+ applySubst :: [(String, Type)] -> Type -> Maybe Type
371+ applySubst subst = everywhereM (mkM replace)
372+ where
373+ replace (TypeVar v) = lookup v subst
374+ replace other = Just other
375+ -- Choose the simplest DictionaryValues from a list of candidates
376+ -- The reason for this function is as follows:
377+ -- When considering overlapping instances, we don't want to consider the same dictionary
378+ -- to be an overlap of itself when obtained as a superclass of another class.
379+ -- Observing that we probably don't want to select a superclass instance when an instance
380+ -- is available directly, and that there is no way for a superclass instance to actually
381+ -- introduce an overlap that wouldn't have been there already, we simply remove dictionaries
382+ -- obtained as superclass instances if there are simpler instances available.
383+ chooseSimplestDictionaries :: [DictionaryValue] -> [DictionaryValue]
384+ chooseSimplestDictionaries ds = case filter isSimpleDictionaryValue ds of
385+ [] -> ds
386+ simple -> simple
387+ isSimpleDictionaryValue SubclassDictionaryValue{} = False
388+ isSimpleDictionaryValue (DependentDictionaryValue _ ds) = all isSimpleDictionaryValue ds
389+ isSimpleDictionaryValue _ = True
390+ -- |
391+ -- Get the "trace" of a DictionaryValue - that is, remove all SubclassDictionaryValue
392+ -- data constructors
393+ --
394+ dictTrace :: DictionaryValue -> DictionaryValue
395+ dictTrace (DependentDictionaryValue fnName dicts) = DependentDictionaryValue fnName $ map dictTrace dicts
396+ dictTrace (SubclassDictionaryValue dict _ _) = dictTrace dict
397+ dictTrace other = other
343398
344399-- |
345400-- Check all values in a list pairwise match a predicate
@@ -355,7 +410,7 @@ pairwise p (x : xs) = all (p x) xs && pairwise p xs
355410unifiesWith :: Environment -> Type -> Type -> Bool
356411unifiesWith _ (TUnknown _) _ = True
357412unifiesWith _ _ (TUnknown _) = True
358−unifiesWith _ (Skolem s1 _) (Skolem s2 _) | s1 == s2 = True
413+unifiesWith _ (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = True
359414unifiesWith _ (TypeVar v1) (TypeVar v2) | v1 == v2 = True
360415unifiesWith _ (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = True
361416unifiesWith e (TypeApp h1 t1) (TypeApp h2 t2) = unifiesWith e h1 h2 && unifiesWith e t1 t2
@@ -371,7 +426,7 @@ unifiesWith _ _ _ = False
371426-- and return a substitution from type variables to types which makes the type heads unify.
372427--
373428typeHeadsAreEqual :: ModuleName -> Environment -> Type -> Type -> Maybe [(String, Type)]
374−typeHeadsAreEqual _ _ (Skolem s1 _) (Skolem s2 _) | s1 == s2 = Just []
429+typeHeadsAreEqual _ _ (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = Just []
375430typeHeadsAreEqual _ _ t (TypeVar v) = Just [(v, t)]
376431typeHeadsAreEqual _ _ (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = Just []
377432typeHeadsAreEqual m e (TypeApp h1 t1) (TypeApp h2 t2) = (++) <$> typeHeadsAreEqual m e h1 h2 <*> typeHeadsAreEqual m e t1 t2
@@ -405,7 +460,7 @@ skolemEscapeCheck root@TypedValue{} =
405460 collectSkolems :: Type -> [SkolemScope]
406461 collectSkolems = nub . everything (++) (mkQ [] collect)
407462 where
408− collect (Skolem _ scope) = [scope]
463+ collect (Skolem _ _ scope) = [scope]
409464 collect _ = []
410465 go _ scos = ([], scos)
411466 findBindingScope :: SkolemScope -> Maybe Value
@@ -454,7 +509,7 @@ instantiatePolyTypeWithUnknowns val (ForAll ident ty _) = do
454509instantiatePolyTypeWithUnknowns val (ConstrainedType constraints ty) = do
455510 dicts <- getTypeClassDictionaries
456511 (_, ty') <- instantiatePolyTypeWithUnknowns (error "Types under a constraint cannot themselves be constrained") ty
457− return (foldl App val (map (flip TypeClassDictionary dicts) constraints), ty')
512+ return (foldl App val (map (flip (TypeClassDictionary True) dicts) constraints), ty')
458513instantiatePolyTypeWithUnknowns val ty = return (val, ty)
459514
460515-- |
@@ -578,7 +633,7 @@ infer' (Var var) = do
578633 case ty of
579634 ConstrainedType constraints ty' -> do
580635 dicts <- getTypeClassDictionaries
581− return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) constraints)) ty'
636+ return $ TypedValue True (foldl App (Var var) (map (flip (TypeClassDictionary True) dicts) constraints)) ty'
582637 _ -> return $ TypedValue True (Var var) ty
583638infer' v@(Constructor c) = do
584639 env <- getEnv
@@ -600,6 +655,9 @@ infer' (IfThenElse cond th el) = do
600655infer' (Let ds val) = do
601656 (ds', val'@(TypedValue _ _ valTy)) <- inferLetBinding [] ds val infer
602657 return $ TypedValue True (Let ds' val') valTy
658+infer' (SuperClassDictionary className tys) = do
659+ dicts <- getTypeClassDictionaries
660+ return $ TypeClassDictionary False (className, tys) dicts
603661infer' (TypedValue checkType val ty) = do
604662 Just moduleName <- checkCurrentModule <$> get
605663 kind <- liftCheck $ kindOf moduleName ty
@@ -735,7 +793,18 @@ newSkolemScope = SkolemScope . runUnknown <$> fresh'
735793-- Skolemize a type variable by replacing its instances with fresh skolem constants
736794--
737795skolemize :: String -> Int -> SkolemScope -> Type -> Type
738−skolemize ident sko scope = replaceTypeVars ident (Skolem sko scope)
796+skolemize ident sko scope = replaceTypeVars ident (Skolem ident sko scope)
797+
798+-- |
799+-- This function has one purpose - to skolemize type variables appearing in a
800+-- SuperClassDictionary placeholder. These type variables are somewhat unique since they are the
801+-- only example of scoped type variables.
802+--
803+skolemizeTypesInValue :: String -> Int -> SkolemScope -> Value -> Value
804+skolemizeTypesInValue ident sko scope = everywhere (mkT go)
805+ where
806+ go (SuperClassDictionary c ts) = SuperClassDictionary c (map (skolemize ident sko scope) ts)
807+ go other = other
739808
740809-- |
741810-- Introduce skolem scope at every occurence of a ForAll
@@ -766,7 +835,8 @@ check' val (ForAll ident ty _) = do
766835 scope <- newSkolemScope
767836 sko <- newSkolemConstant
768837 let sk = skolemize ident sko scope ty
769− val' <- check val sk
838+ let skVal = skolemizeTypesInValue ident sko scope val
839+ val' <- check skVal sk
770840 return $ TypedValue True val' (ForAll ident ty (Just scope))
771841check' val t@(ConstrainedType constraints ty) = do
772842 dictNames <- forM constraints $ \(Qualified _ (ProperName className), _) -> do
@@ -812,6 +882,19 @@ check' v@(Var var) ty = do
812882 case v' of
813883 Nothing -> throwError . strMsg $ "Unable to check type subsumption"
814884 Just v'' -> return $ TypedValue True v'' ty'
885+check' (SuperClassDictionary className tys) _ = do
886+ -- |
887+ -- Here, we replace a placeholder for a superclass dictionary with a regular
888+ -- TypeClassDictionary placeholder. The reason we do this is that it is necessary to have the
889+ -- correct super instance dictionaries in scope, and these are not available when the type class
890+ -- declaration gets desugared.
891+ --
892+ -- Note also that the first argument to TypeClassDictionary is False, meaning we _do not_ want
893+ -- to consider superclass instances when searching for this dictionary - doing so might lead
894+ -- to traversing a cycle in the instance graph.
895+ --
896+ dicts <- getTypeClassDictionaries
897+ return $ TypeClassDictionary False (className, tys) dicts
815898check' (TypedValue checkType val ty1) ty2 = do
816899 Just moduleName <- checkCurrentModule <$> get
817900 kind <- liftCheck $ kindOf moduleName ty1
@@ -883,7 +966,7 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
883966 go [] [] REmpty = return []
884967 go [] [] u@(TUnknown _) = do u =?= REmpty
885968 return []
886− go [] [] (Skolem _ _) | lax = return []
969+ go [] [] (Skolem _ _ _) | lax = return []
887970 go [] ((p, _): _) _ | lax = return []
888971 | otherwise = throwError $ mkErrorStack ("Object does not have property " ++ p) (Just (ValueError (ObjectLiteral ps)))
889972 go ((p,_):_) [] REmpty = throwError $ mkErrorStack ("Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row) (Just (ValueError (ObjectLiteral ps)))
@@ -944,7 +1027,7 @@ checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do
9441027 checkFunctionApplication fn ty arg ret
9451028checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
9461029 dicts <- getTypeClassDictionaries
947− checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) constraints)) fnTy arg ret
1030+ checkFunctionApplication' (foldl App fn (map (flip (TypeClassDictionary True) dicts) constraints)) fnTy arg ret
9481031checkFunctionApplication' _ fnTy arg _ = throwError . strMsg $ "Cannot apply a function of type "
9491032 ++ prettyPrintType fnTy
9501033 ++ " to argument " ++ prettyPrintValue arg
@@ -987,7 +1070,7 @@ subsumes' val ty1 (SaturatedTypeSynonym name tyArgs) = do
9871070subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
9881071 dicts <- getTypeClassDictionaries
9891072 _ <- subsumes' Nothing ty1 ty2
990− return . Just $ foldl App val (map (flip TypeClassDictionary dicts) constraints)
1073+ return . Just $ foldl App val (map (flip (TypeClassDictionary True) dicts) constraints)
9911074subsumes' val (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyObject && f2 == tyObject = do
9921075 let
9931076 (ts1, r1') = rowToList r1