@@ -14,14 +14,15 @@ module Language.PureScript.TypeChecker.Entailment
1414import Prelude.Compat
1515import Protolude (ordNub )
1616
17- import Control.Applicative ((<|>) )
17+ import Control.Applicative ((<|>) , empty )
1818import Control.Arrow (second , (&&&) )
1919import Control.Monad.Error.Class (MonadError (.. ))
2020import Control.Monad.State
2121import Control.Monad.Supply.Class (MonadSupply (.. ))
22+ import Control.Monad.Trans.Maybe (MaybeT (.. ))
2223import Control.Monad.Writer
2324
24- import Data.Foldable (for_ , fold , toList )
25+ import Data.Foldable (for_ , fold , foldl' , toList )
2526import Data.Function (on )
2627import Data.Functor (($>) )
2728import Data.List (minimumBy , groupBy , nubBy , sortBy , zipWith4 )
@@ -39,7 +40,7 @@ import Language.PureScript.Environment
3940import Language.PureScript.Errors
4041import Language.PureScript.Names
4142import Language.PureScript.Roles
42- import Language.PureScript.TypeChecker.Kinds (elaborateKind , unifyKinds )
43+ import Language.PureScript.TypeChecker.Kinds (elaborateKind , kindOf , unifyKinds )
4344import Language.PureScript.TypeChecker.Monad
4445import Language.PureScript.TypeChecker.Roles
4546import Language.PureScript.TypeChecker.Synonyms
@@ -168,12 +169,18 @@ entails
168169entails SolverOptions {.. } constraint context hints =
169170 solve constraint
170171 where
172+ forClassNameM :: Environment -> InstanceContext -> Qualified (ProperName 'ClassName) -> [SourceType ] -> [SourceType ] -> m [TypeClassDict ]
173+ forClassNameM env ctx cn@ C. Coercible kinds args =
174+ solveCoercible env kinds args >>=
175+ pure . fromMaybe (forClassName env ctx cn kinds args)
176+ forClassNameM env ctx cn kinds args =
177+ pure $ forClassName env ctx cn kinds args
178+
171179 forClassName :: Environment -> InstanceContext -> Qualified (ProperName 'ClassName) -> [SourceType ] -> [SourceType ] -> [TypeClassDict ]
172180 forClassName _ ctx cn@ C. Warn _ [msg] =
173181 -- Prefer a warning dictionary in scope if there is one available.
174182 -- This allows us to defer a warning by propagating the constraint.
175183 findDicts ctx cn Nothing ++ [TypeClassDictionaryInScope [] 0 (WarnInstance msg) [] C. Warn [] [] [msg] Nothing ]
176- forClassName env _ C. Coercible kinds args | Just dicts <- solveCoercible env kinds args = dicts
177184 forClassName _ _ C. IsSymbol _ args | Just dicts <- solveIsSymbol args = dicts
178185 forClassName _ _ C. SymbolCompare _ args | Just dicts <- solveSymbolCompare args = dicts
179186 forClassName _ _ C. SymbolAppend _ args | Just dicts <- solveSymbolAppend args = dicts
@@ -225,10 +232,12 @@ entails SolverOptions{..} constraint context hints =
225232 Nothing -> throwError . errorMessage $ UnknownClass className'
226233 Just tcd -> pure tcd
227234
235+ dicts <- lift . lift $ forClassNameM env (combineContexts context inferred) className' kinds'' tys''
236+
228237 let instances = do
229238 chain <- groupBy ((==) `on` tcdChain) $
230239 sortBy (compare `on` (tcdChain &&& tcdIndex)) $
231- forClassName env (combineContexts context inferred) className' kinds'' tys''
240+ dicts
232241 -- process instances in a chain in index order
233242 let found = for chain $ \ tcd ->
234243 -- Make sure the type unifies with the type in the type instance definition
@@ -381,11 +390,11 @@ entails SolverOptions{..} constraint context hints =
381390 subclassDictionaryValue dict className index =
382391 App (Accessor (mkString (superclassName className index)) dict) valUndefined
383392
384- solveCoercible :: Environment -> [SourceType ] -> [SourceType ] -> Maybe [TypeClassDict ]
385- solveCoercible env kinds [a, b] = do
393+ solveCoercible :: Environment -> [SourceType ] -> [SourceType ] -> m ( Maybe [TypeClassDict ])
394+ solveCoercible env kinds [a, b] = runMaybeT $ do
386395 let tySynMap = typeSynonyms env
387396 kindMap = types env
388- replaceTySyns = either ( const Nothing ) Just . replaceAllTypeSynonymsM tySynMap kindMap
397+ replaceTySyns = lift . replaceAllTypeSynonymsM tySynMap kindMap
389398 a' <- replaceTySyns a
390399 b' <- replaceTySyns b
391400 -- Solving terminates when the two arguments are the same. Since we
@@ -394,40 +403,43 @@ entails SolverOptions{..} constraint context hints =
394403 if a' == b'
395404 then pure [TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C. Coercible [] kinds [a, b] Nothing ]
396405 else do
406+ lift $ do
407+ (_, kind) <- kindOf a'
408+ (_, kind') <- kindOf b'
409+ unifyKinds kind kind'
397410 -- When solving must reduce and recurse, it doesn't matter whether we
398411 -- reduce the first or second argument -- if the constraint is
399412 -- solvable, either path will yield the same outcome. Consequently we
400413 -- just try the first argument first and the second argument second.
401- ws <- coercibleWanteds env a' b' <|> coercibleWanteds env b' a'
414+ ws <- ( MaybeT $ coercibleWanteds env a' b') <|> ( MaybeT $ coercibleWanteds env b' a')
402415 pure [TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C. Coercible [] kinds [a, b] (Just ws)]
403- solveCoercible _ _ _ = Nothing
416+ solveCoercible _ _ _ = pure Nothing
404417
405418 -- | Take two types, @a@ and @b@ representing a desired constraint
406419 -- @Coercible a b@ and reduce them to a set of simpler wanted constraints
407420 -- whose satisfaction will yield the goal.
408- coercibleWanteds :: Environment -> SourceType -> SourceType -> Maybe [SourceConstraint ]
421+ coercibleWanteds :: Environment -> SourceType -> SourceType -> m ( Maybe [SourceConstraint ])
409422 coercibleWanteds env a b
410423 | (TypeConstructor _ aTyName, _, axs) <- unapplyTypes a
411424 , (TypeConstructor _ bTyName, _, bxs) <- unapplyTypes b
412425 , Just (aTyKind, _) <- M. lookup aTyName $ types env
413426 , Just (bTyKind, _) <- M. lookup bTyName $ types env
414427 , (aks, kind) <- unapplyKinds aTyKind
415428 , (bks, _) <- unapplyKinds bTyKind
416- , i <- length aks - length axs
417- , j <- length bks - length bxs
418- , i > 0 && j > 0 = do
429+ , length axs < length aks
430+ , length bxs < length bks = do
419431 -- If both arguments have kind @k1 -> k2@ (e.g. @data D a b = D a@
420432 -- in the constraint @Coercible (D a) (D a')@), yield a new wanted
421433 -- constraint in terms of the types saturated with the same variables
422434 -- (e.g. @Coercible (D a t0) (D a' t0)@ in the exemple).
423- let aTyVars = S. fromList $ usedTypeVariables a
424- bTyVars = S. fromList $ usedTypeVariables b
425- saturate ' = saturate $ aTyVars `S.union` bTyVars
426- pure [srcCoercibleConstraint kind (saturate' a i) (saturate ' b j) ]
435+ tys <- traverse freshTypeWithKind aks
436+ let a' = foldl' srcTypeApp a $ drop ( length axs) tys
437+ b ' = foldl' srcTypeApp b $ drop ( length bxs) tys
438+ pure $ Just [srcCoercibleConstraint kind a ' b' ]
427439 | (TypeConstructor _ aTyName, _, axs) <- unapplyTypes a
428440 , (TypeConstructor _ bTyName, _, bxs) <- unapplyTypes b
429441 , not (null axs) && not (null bxs) && aTyName == bTyName
430- , Just (aTyKind, _) <- M. lookup aTyName (types env) = do
442+ , Just (aTyKind, _) <- M. lookup aTyName (types env) = runMaybeT $ do
431443 -- If both arguments are applications of the same type constructor
432444 -- (e.g. @data D a b = D a@ in the constraint
433445 -- @Coercible (D a b) (D a' b')@), infer the roles of the type
@@ -445,13 +457,13 @@ entails SolverOptions{..} constraint context hints =
445457 -- means there are cases we should be able to handle that
446458 -- we currently can't, but is at least sound.
447459 | ax == bx ->
448- Just []
460+ pure []
449461 | otherwise ->
450- Nothing
462+ empty
451463 Representational ->
452- Just [srcCoercibleConstraint kx ax bx]
464+ pure [srcCoercibleConstraint kx ax bx]
453465 Phantom ->
454- Just []
466+ pure []
455467 fmap concat $ sequence $ zipWith4 f roles kinds axs bxs
456468 | (TypeConstructor _ tyName, _, xs) <- unapplyTypes a
457469 , Just (tvs, wrappedTy, _) <- lookupNewtypeConstructor env tyName = do
@@ -461,10 +473,10 @@ entails SolverOptions{..} constraint context hints =
461473 -- terms of that type with the type arguments substituted in (e.g.
462474 -- @Coercible (T[X/a]) b = Coercible X b@ in the example).
463475 let wrappedTySub = replaceAllTypeVars (zip tvs xs) wrappedTy
464- pure [srcCoercibleConstraint kindType wrappedTySub b]
476+ pure $ Just [srcCoercibleConstraint kindType wrappedTySub b]
465477 | otherwise =
466478 -- In all other cases we can't solve the constraint.
467- Nothing
479+ pure Nothing
468480
469481 srcCoercibleConstraint :: SourceType -> SourceType -> SourceType -> SourceConstraint
470482 srcCoercibleConstraint k a b = srcConstraint C. Coercible [k] [a, b] Nothing
0 commit comments