module Top.Types.Schemes where
import Top.Types.Primitive
import Top.Types.Quantification
import Top.Types.Qualification
import Top.Types.Substitution
import Top.Types.Synonym
import Top.Types.Unification
import Top.Types.Classes
import Data.List
import qualified Data.Map as M
type TpScheme = Forall QType
type QType = Qualification Predicates Tp
class IsTpScheme a where
toTpScheme :: a -> TpScheme
instance IsTpScheme TpScheme where
toTpScheme = id
instance IsTpScheme QType where
toTpScheme = noQuantifiers
instance IsTpScheme Tp where
toTpScheme = noQuantifiers . ([] .=>.)
arityOfTpScheme :: TpScheme -> Int
arityOfTpScheme = arityOfTp . unqualify . unquantify
genericInstanceOf :: OrderedTypeSynonyms -> ClassEnvironment -> TpScheme -> TpScheme -> Bool
genericInstanceOf synonyms classes scheme1 scheme2 =
let
s1 = skolemizeFTV scheme1
s2 = skolemizeFTV scheme2
sub = listToSubstitution (zip (quantifiers s1) [ TCon ('+':show i) | i <- [0 :: Int ..]])
(ps1, tp1) = split (sub |-> unquantify s1)
(ps2, tp2) = split (snd (instantiate 123456789 s2))
in case mguWithTypeSynonyms synonyms tp1 tp2 of
Left _ -> False
Right (_,sub2) -> entailList synonyms classes ps1 (sub2 |-> ps2)
isOverloaded :: TpScheme -> Bool
isOverloaded = not . null . qualifiers . unquantify
makeScheme :: [Int] -> Predicates -> Tp -> TpScheme
makeScheme monos preds tp =
let is = ftv tp \\ monos
p = any (`elem` is) . ftv
in quantify is (filter p preds .=>. tp)
instantiateWithNameMap :: Int -> TpScheme -> (Int, Predicates, Tp)
instantiateWithNameMap unique (Quantification (qs,nm,qtp)) =
let sub = listToSubstitution [ (i,TCon s) | (i,s) <- nm, i `elem` qs ]
(u, qtp') = instantiate unique (Quantification (qs \\ map fst nm, [], sub |-> qtp))
(ps, tp) = split qtp'
in (u, ps, tp)
instance (ShowQualifiers q, Show a) => ShowQuantors (Qualification q a)
type Scheme qs = Forall (Qualification qs Tp)
data Sigma qs = SigmaVar SigmaVar
| SigmaScheme (Scheme qs)
type SigmaVar = Int
instance (ShowQualifiers qs, Substitutable qs) => Show (Sigma qs) where
show (SigmaVar i) = 's':show i
show (SigmaScheme s) = show s
instance Substitutable qs => Substitutable (Sigma qs) where
_ |-> sv@(SigmaVar _) = sv
sub |-> (SigmaScheme s) = SigmaScheme (sub |-> s)
ftv (SigmaVar _) = []
ftv (SigmaScheme s) = ftv s
instance (Substitutable qs, ShowQualifiers qs) => ShowQuantors (Sigma qs) where
showQuantorsWithout options sigma =
case sigma of
SigmaVar _ -> show sigma
SigmaScheme ts -> showQuantorsWithout options ts
type TpSchemeMap = M.Map SigmaVar TpScheme
type SigmaPreds = Sigma Predicates
class IsSigmaPreds a where
toSigmaPreds :: a -> SigmaPreds
instance IsSigmaPreds SigmaPreds where toSigmaPreds = id
instance IsSigmaPreds TpScheme where toSigmaPreds = SigmaScheme . toTpScheme
instance IsSigmaPreds QType where toSigmaPreds = SigmaScheme . toTpScheme
instance IsSigmaPreds Tp where toSigmaPreds = SigmaScheme . toTpScheme
instance IsSigmaPreds Int where toSigmaPreds = SigmaVar