@@ -20,7 +20,7 @@ module Language.PureScript.TypeChecker.Types (
2020) where
2121
2222import Data.List
23−import Data.Maybe (isNothing, isJust, fromMaybe)
23+import Data.Maybe (maybeToList, isNothing, isJust, fromMaybe)
2424import qualified Data.Data as D
2525import Data.Generics
2626 (mkM, everywhereM, everything, mkT, something, everywhere, mkQ)
@@ -188,8 +188,29 @@ replaceTypeClassDictionaries = everywhereM (mkM go)
188188 go (TypeClassDictionary constraint dicts) = entails dicts constraint
189189 go other = return other
190190
191−entails :: [(Ident, Qualified ProperName, Type)] -> (Qualified ProperName, Type) -> Check Value
192−entails _ _ = return $ Var $ Qualified Nothing $ Ident "placeholder" -- TODO
191+entails :: [(Ident, [(Qualified ProperName, Type)], Qualified ProperName, Type)] -> (Qualified ProperName, Type) -> Check Value
192+entails context goal =
193+ case go goal of
194+ [] -> throwError $ "No type class instance for " ++ show goal ++ " in context " ++ show context
195+ (dict : _) -> return dict
196+ where
197+ go (className, ty) = [ App (Var (Qualified Nothing fnName)) args
198+ | (fnName, subgoals, className', ty') <- context
199+ , className == className'
200+ , subst <- maybeToList $ typeHeadsAreEqual ty ty'
201+ , args <- forM (replaceAllTypeVars subst subgoals) go ]
202+ typeHeadsAreEqual :: Type -> Type -> Maybe [(String, Type)]
203+ typeHeadsAreEqual String String = Just []
204+ typeHeadsAreEqual Number Number = Just []
205+ typeHeadsAreEqual Boolean Boolean = Just []
206+ typeHeadsAreEqual (Skolem s1) (Skolem s2) | s1 == s2 = Just []
207+ typeHeadsAreEqual (Array ty1) (Array ty2) = typeHeadsAreEqual ty1 ty2
208+ typeHeadsAreEqual (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = Just []
209+ typeHeadsAreEqual (TypeApp h1 (TypeVar v)) (TypeApp h2 arg) = do
210+ m <- typeHeadsAreEqual h1 h2
211+ return $ (v, arg) : m
212+ typeHeadsAreEqual t1@(TypeApp _ _) t2@(TypeApp _ (TypeVar _)) = typeHeadsAreEqual t2 t1
213+ typeHeadsAreEqual _ _ = Nothing
193214
194215escapeCheck :: Value -> Type -> Subst ()
195216escapeCheck value ty = do
@@ -612,7 +633,7 @@ check' val (ForAll idents ty) = do
612633 check val sk
613634check' val (ConstrainedType constraints ty) = do
614635 let dictName = Ident "__dict" -- TODO
615− val' <- withTypeClassDictionaries (map (\(className, instanceTy) -> (dictName, className, instanceTy)) constraints) $ check val ty
636+ val' <- withTypeClassDictionaries (map (\(className, instanceTy) -> (dictName, [], className, instanceTy)) constraints) $ check val ty
616637 return $ Abs (map (\_ -> dictName) constraints) val'
617638check' val u@(TUnknown _) = do
618639 val'@(TypedValue _ ty) <- infer val