recover-rtti-0.6.0: tests/Test/RecoverRTTI/ConcreteClassifier/Compatibility.hs
module Test.RecoverRTTI.ConcreteClassifier.Compatibility (
Compatible(..)
, CompatibleNP(..)
, compatibleClassifier
) where
import Data.SOP.NP
import Data.Type.Equality
import Debug.RecoverRTTI
import Test.RecoverRTTI.ConcreteClassifier
import Test.RecoverRTTI.Staged
import Test.RecoverRTTI.UserDefined
data Compatible a b where
CompatibleSame :: Compatible a a
CompatibleDeferred :: Compatible a Deferred
CompatibleF1 :: Compatible a b -> Compatible (f a) (f b)
CompatibleF2 :: Compatible a b
-> Compatible a' b'
-> Compatible (f a a') (f b b')
CompatibleFn :: CompatibleNP as bs -> Compatible (f as) (f bs)
data CompatibleNP as bs where
CompatibleNil :: CompatibleNP '[] '[]
CompatibleNP :: Compatible a b
-> CompatibleNP as bs
-> CompatibleNP (a ': as) (b ': bs)
-- | Is the inferred classifier compatible with the generated classifier?
compatibleClassifier :: Concrete a -> UserClassifier b -> Maybe (Compatible a b)
compatibleClassifier = \concrete inferred ->
case (concrete, inferred) of
(CC_Prim c, C_Prim c') -> compatibleRefl <$> samePrim c c'
(CC_Other c, C_Other c') -> compatibleUser c c'
(CC_Maybe{} , C_Maybe ) -> Just deferredF1
(CC_Ratio{} , C_Ratio ) -> Just deferredF1
(CC_Set{} , C_Set ) -> Just deferredF1
(CC_IntMap{} , C_IntMap ) -> Just deferredF1
(CC_Tree{} , C_Tree ) -> Just deferredF1
(CC_HashSet{} , C_HashSet ) -> Just deferredF1
(CC_Sequence c , C_Sequence c') -> listElem c c'
(CC_List c , C_List c') -> listElem c c'
(CC_HM_Array c , C_HM_Array c') -> listElem c c'
(CC_Vector_Boxed c , C_Vector_Boxed c') -> listElem c c'
(CC_Prim_Array c , C_Prim_Array c') -> listElem c c'
(CC_Either{} , C_Either ) -> Just deferredF2
(CC_HashMap{} , C_HashMap ) -> Just deferredF2
(CC_Map{} , C_Map ) -> Just deferredF2
(CC_Tuple cs , C_Tuple cs' ) -> compatibleTuple cs cs'
_otherwise -> Nothing
where
listElem ::
Concrete a
-> ClassifyListElem b
-> Maybe (Compatible (f a) (f b))
listElem = \concrete inferred ->
case (concrete, inferred) of
(_anything , C_List_Deferred) -> Just $ CompatibleF1 CompatibleDeferred
(CC_Prim C_Char , C_List_Char ) -> Just $ CompatibleF1 CompatibleSame
_otherwise -> Nothing
_checkedAllCases :: Concrete a -> ()
_checkedAllCases = \case
CC_Either{} -> ()
CC_HashMap{} -> ()
CC_HashSet{} -> ()
CC_HM_Array{} -> ()
CC_IntMap{} -> ()
CC_List{} -> ()
CC_Map{} -> ()
CC_Maybe{} -> ()
CC_Other{} -> ()
CC_Prim_Array{} -> ()
CC_Prim{} -> ()
CC_Ratio{} -> ()
CC_Sequence{} -> ()
CC_Set{} -> ()
CC_Tree{} -> ()
CC_Tuple{} -> ()
CC_Vector_Boxed{} -> ()
CC_Void{} -> ()
compatibleUser :: ConcreteUser a -> ClassifyUser b -> Maybe (Compatible a b)
compatibleUser = \concrete inferred ->
case (concrete, inferred) of
(CC_Simple , C_Simple ) -> Just CompatibleSame
(CC_NonRec{} , C_NonRec ) -> Just deferredF1
(CC_Rec{} , C_Rec ) -> Just deferredF1
(CC_Unlifted , C_Unlifted) -> Just CompatibleSame
_otherwise -> Nothing
where
_checkedAllCases :: ConcreteUser a -> ()
_checkedAllCases = \case
CC_Simple -> ()
CC_NonRec{} -> ()
CC_Rec{} -> ()
CC_Unlifted -> ()
compatibleTuple ::
Concretes as
-> Classifiers_ ClassifyUser bs
-> Maybe (Compatible (WrappedTuple as) (WrappedTuple bs))
compatibleTuple = \(Concretes concrete) (Classifiers_ inferred) ->
CompatibleFn <$> go concrete inferred
where
go ::
NP Concrete as
-> NP UserClassifier bs
-> Maybe (CompatibleNP as bs)
go Nil Nil = Just CompatibleNil
go Nil (_ :* _) = Nothing
go (_ :* _) Nil = Nothing
go (a :* as) (b :* bs) =
pure CompatibleNP
<*> compatibleClassifier a b
<*> go as bs
{-------------------------------------------------------------------------------
Internal auxiliary
-------------------------------------------------------------------------------}
compatibleRefl :: (a :~: b) -> Compatible a b
compatibleRefl Refl = CompatibleSame
deferredF1 :: Compatible (f a) (f Deferred)
deferredF1 = CompatibleF1 CompatibleDeferred
deferredF2 :: Compatible (f a b) (f Deferred Deferred)
deferredF2 = CompatibleF2 CompatibleDeferred CompatibleDeferred