@@ -18,7 +18,7 @@ import Data.Aeson ((.:), (.=), withObject, object)
1818import Data.Aeson.Types (Parser , Value )
1919import Data.Hashable (Hashable (.. ))
2020import Data.Text (Text )
21- import Data.Typeable (typeOf , typeRepTyCon , typeRep , Typeable , cast )
21+ import Data.Typeable (Typeable , cast , splitTyConApp , typeOf , typeRep )
2222#if !MIN_VERSION_base(4, 11, 0)
2323import Data.Semigroup
2424#endif
@@ -165,12 +165,15 @@ instance DatabasePredicate TableHasIndex where
165165-- | Match a given item's type against a type-level application with the given
166166-- type constructor. Applies the given function and returns 'Just' its result on match,
167167-- 'Nothing' otherwise.
168+ -- Unlike 'cast', this function does not require @a@ type to be instance of 'Typeable'.
168169withTyCon
169170 :: forall (con :: * -> * ) (item :: * ) r .
170171 (Typeable con , Typeable item )
171172 => (forall a . con a -> r ) -> item -> Maybe r
172173withTyCon f x = do
173- guard (typeRepTyCon (typeRep (Proxy @ item )) == typeRepTyCon (typeOf x))
174+ (itemTyCon, itemTyArgs@ (_ : _)) <- pure $ splitTyConApp (typeOf x)
175+ (conTyCon, conTyArgs) <- pure $ splitTyConApp (typeRep (Proxy @ con ))
176+ guard (itemTyCon == conTyCon && init itemTyArgs == conTyArgs)
174177 return (f $ unsafeCoerce x)
175178
176179-- | Convert gathered indices into checks.
0 commit comments