module Control.Super.Plugin.Instance
( instanceClass
, instanceClassTyCon
, instanceTopTyCons
, instanceTyArgs
, isClassInstance
, isMonoTyConInstance
, isPolyTyConInstance
) where
import InstEnv
( ClsInst(..)
, instanceHead )
import Type ( Type )
import Class ( Class, classTyCon )
import TyCon ( TyCon )
import qualified Control.Super.Plugin.Collection.Set as S
import Control.Super.Plugin.Utils ( collectTopTyCons )
isClassInstance :: Class -> ClsInst -> Bool
isClassInstance cls inst = instanceClass inst == cls
instanceClass :: ClsInst -> Class
instanceClass = is_cls
instanceClassTyCon :: ClsInst -> TyCon
instanceClassTyCon inst = classTyCon $ instanceClass inst
instanceTopTyCons :: ClsInst -> S.Set TyCon
instanceTopTyCons = collectTopTyCons . instanceTyArgs
instanceTyArgs :: ClsInst -> [Type]
instanceTyArgs inst = args
where (_, _, args) = instanceHead inst
isMonoTyConInstance :: TyCon -> Class -> ClsInst -> Bool
isMonoTyConInstance tc cls inst
= isClassInstance cls inst
&& all (== S.singleton tc) argTopTcs
where
argTopTcs :: [S.Set TyCon]
argTopTcs = fmap ( collectTopTyCons . (: []) ) $ instanceTyArgs inst
isPolyTyConInstance :: Class -> ClsInst -> Bool
isPolyTyConInstance cls inst = isClassInstance cls inst && allNotEmpty && not (allEqual argTopTcs)
where
argTopTcs :: [S.Set TyCon]
argTopTcs = fmap ( collectTopTyCons . (: []) ) $ instanceTyArgs inst
allNotEmpty = all (not . S.null) argTopTcs
allEqual [] = True
allEqual (a:as) = all (a ==) as