@@ -22,6 +22,7 @@ import Data.Foldable (for_, traverse_)
22import Data.List (nub, nubBy, (\\), sort, group)
22import Data.List (nub, nubBy, (\\), sort, group)
23import Data.Maybe
23import Data.Maybe
24import qualified Data.Map as M
24import qualified Data.Map as M
25+import qualified Data.Set as S
25import Data.Monoid ((<>))
26import Data.Monoid ((<>))
26import qualified Data.Text as T
27import qualified Data.Text as T
27import Data.Text (Text)
28import Data.Text (Text)
@@ -124,12 +125,7 @@ addTypeClass moduleName pn args implies dependencies ds =
124 modify $ \st -> st { checkEnv = (checkEnv st) { typeClasses = M.insert (Qualified (Just moduleName) pn) newClass (typeClasses . checkEnv $ st) } }
125 modify $ \st -> st { checkEnv = (checkEnv st) { typeClasses = M.insert (Qualified (Just moduleName) pn) newClass (typeClasses . checkEnv $ st) } }
126 newClass :: TypeClassData
127 newClass :: TypeClassData
127− newClass =
128+ newClass = makeTypeClassData args (map toPair ds) implies dependencies
128− TypeClassData { typeClassArguments = args
129− , typeClassMembers = map toPair ds
130− , typeClassSuperclasses = implies
131− , typeClassDependencies = dependencies
134 toPair (TypeDeclaration ident ty) = (ident, ty)
130 toPair (TypeDeclaration ident ty) = (ident, ty)
135 toPair (PositionedDeclaration _ _ d) = toPair d
131 toPair (PositionedDeclaration _ _ d) = toPair d
@@ -155,18 +151,28 @@ checkDuplicateTypeArguments args = for_ firstDup $ \dup ->
155 firstDup = listToMaybe $ args \\ nub args
151 firstDup = listToMaybe $ args \\ nub args
157checkTypeClassInstance
153checkTypeClassInstance
158− :: (MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
154+ :: (MonadState CheckState m, MonadError MultipleErrors m)
159− => ModuleName
155+ => TypeClassData
156+ -> Int -- ^ index of type class argument
162−checkTypeClassInstance _ (TypeVar _) = return ()
159+checkTypeClassInstance cls i = check where
160+ -- If the argument is determined via fundeps then we are less restrictive in
161+ -- what type is allowed. This is because the type cannot be used to influence
162+ -- which instance is selected. Currently the only weakened restriction is that
163+ -- row types are allowed in determined type class arguments.
164+ isFunDepDetermined = S.member i (typeClassDeterminedArguments cls)
166+ TypeVar _ -> return ()
163−checkTypeClassInstance _ (TypeLevelString _) = return ()
167+ TypeLevelString _ -> return ()
164−checkTypeClassInstance _ (TypeConstructor ctor) = do
168+ TypeConstructor ctor -> do
165− env <- getEnv
169+ env <- getEnv
166− when (ctor `M.member` typeSynonyms env) . throwError . errorMessage $ TypeSynonymInstance
170+ when (ctor `M.member` typeSynonyms env) . throwError . errorMessage $ TypeSynonymInstance
167− return ()
171+ return ()
168−checkTypeClassInstance m (TypeApp t1 t2) = checkTypeClassInstance m t1 >> checkTypeClassInstance m t2
172+ TypeApp t1 t2 -> check t1 >> check t2
173+ REmpty | isFunDepDetermined -> return ()
174+ RCons _ hd tl | isFunDepDetermined -> check hd >> check tl
169−checkTypeClassInstance _ ty = throwError . errorMessage $ InvalidInstanceHead ty
175+ ty -> throwError . errorMessage $ InvalidInstanceHead ty
172-- Check that type synonyms are fully-applied in a type
178-- Check that type synonyms are fully-applied in a type
@@ -283,12 +289,16 @@ typeCheckAll moduleName _ = traverse go
283 addTypeClass moduleName pn args implies deps tys
289 addTypeClass moduleName pn args implies deps tys
285 go (d@(TypeInstanceDeclaration dictName deps className tys body)) = rethrow (addHint (ErrorInInstance className tys)) $ do
291 go (d@(TypeInstanceDeclaration dictName deps className tys body)) = rethrow (addHint (ErrorInInstance className tys)) $ do
293+ case M.lookup className (typeClasses env) of
294+ Nothing -> internalError "typeCheckAll: Encountered unknown type class in instance declaration"
295+ Just typeClass -> do
286− traverse_ (checkTypeClassInstance moduleName) tys
296+ sequence_ (zipWith (checkTypeClassInstance typeClass) [0..] tys)
287− checkOrphanInstance dictName className tys
297+ checkOrphanInstance dictName className tys
288− _ <- traverseTypeInstanceBody checkInstanceMembers body
298+ _ <- traverseTypeInstanceBody checkInstanceMembers body
289− let dict = TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) [] className tys (Just deps)
299+ let dict = TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) [] className tys (Just deps)
290− addTypeClassDictionaries (Just moduleName) . M.singleton className $ M.singleton (tcdValue dict) dict
300+ addTypeClassDictionaries (Just moduleName) . M.singleton className $ M.singleton (tcdValue dict) dict
291− return d
301+ return d
292 go (PositionedDeclaration pos com d) =
302 go (PositionedDeclaration pos com d) =
293 warnAndRethrowWithPosition pos $ PositionedDeclaration pos com <$> go d
303 warnAndRethrowWithPosition pos $ PositionedDeclaration pos com <$> go d