{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE PatternSynonyms #-} module Intensional.Scheme ( Scheme, SchemeGen (..), pattern Forall, mono, Intensional.Scheme.unsats ) where import Binary import Intensional.Constraints as Constraints import qualified Data.IntSet as I import qualified Data.IntMap as IntMap import GhcPlugins import Intensional.Types type Scheme = SchemeGen TyCon -- Constrained polymorphic types data SchemeGen d = Scheme { tyvars :: [Name], boundvs :: Domain, body :: TypeGen d, constraints :: ConstraintSet } deriving (Functor, Foldable, Traversable) {-# COMPLETE Forall #-} pattern Forall :: [Name] -> TypeGen d -> SchemeGen d pattern Forall as t <- Scheme as _ t _ where Forall as t = Scheme as mempty t mempty instance Outputable d => Outputable (SchemeGen d) where ppr = prpr ppr instance Binary d => Binary (SchemeGen d) where put_ bh (Scheme as bs t cs) = put_ bh as >> put_ bh (I.toList bs) >> put_ bh t >> put_ bh cs get bh = Scheme <$> get bh <*> (I.fromList <$> get bh) <*> get bh <*> get bh instance Outputable d => Refined (SchemeGen d) where domain s = (domain (body s) Prelude.<> domain (constraints s)) I.\\ boundvs s rename x y s | I.member x (boundvs s) = s | I.member y (boundvs s) = pprPanic "Alpha renaming of polymorphic types is not implemented!" $ ppr (x, y) | otherwise = Scheme { tyvars = tyvars s, boundvs = boundvs s, body = rename x y (body s), constraints = rename x y (constraints s) } prpr _ scheme | constraints scheme /= mempty = hang (hcat [pprTyQuant, pprConQuant, prpr varMap (body scheme)]) 2 (hang (text "where") 2 (prpr varMap (constraints scheme))) | otherwise = hcat [pprTyQuant, pprConQuant, prpr varMap (body scheme)] where numVars = I.size (boundvs scheme) varNames = if numVars > 3 then [ char 'X' GhcPlugins.<> int n | n <- [1..numVars] ] else [ char c | c <- ['X', 'Y', 'Z'] ] varMap = \x -> m IntMap.! x where m = IntMap.fromList $ zip (I.toAscList (boundvs scheme)) varNames pprTyQuant | null (tyvars scheme) = empty | otherwise = hcat [forAllLit <+> fsep (map ppr $ tyvars scheme), dot] pprConQuant | I.null (boundvs scheme) = empty | otherwise = hcat [forAllLit <+> fsep (map varMap $ I.toList (boundvs scheme)), dot] -- Demand a monomorphic type mono :: SchemeGen d -> TypeGen d mono (Forall [] t) = t mono _ = Ambiguous {-| Given a scheme @s@, @unsats s@ is the constraint set containing just the trivially unsatisfiable constraints associated with @s@. -} unsats :: Scheme -> ConstraintSet unsats s = Constraints.unsats (constraints s)