@@ -20,7 +20,7 @@ import Data.Aeson.Types (Parser, Value)
2020import Data.Hashable (Hashable (.. ))
2121import Data.Proxy (Proxy (.. ))
2222import Data.Text (Text )
23- import Data.Typeable (Typeable , cast , typeOf , typeRep , typeRepTyCon )
23+ import Data.Typeable (Typeable , cast , splitTyConApp , typeOf , typeRep )
2424#if !MIN_VERSION_base(4, 11, 0)
2525import Data.Semigroup
2626#endif
@@ -167,12 +167,15 @@ instance DatabasePredicate TableHasIndex where
167167-- | Match a given item's type against a type-level application with the given
168168-- type constructor. Applies the given function and returns 'Just' its result on match,
169169-- 'Nothing' otherwise.
170+ -- Unlike 'cast', this function does not require @a@ type to be instance of 'Typeable'.
170171withTyCon
171172 :: forall (con :: * -> * ) (item :: * ) r .
172173 (Typeable con , Typeable item )
173174 => (forall a . con a -> r ) -> item -> Maybe r
174175withTyCon f x = do
175- guard (typeRepTyCon (typeRep (Proxy @ item )) == typeRepTyCon (typeOf x))
176+ (itemTyCon, itemTyArgs@ (_ : _)) <- pure $ splitTyConApp (typeOf x)
177+ (conTyCon, conTyArgs) <- pure $ splitTyConApp (typeRep (Proxy @ con ))
178+ guard (itemTyCon == conTyCon && init itemTyArgs == conTyArgs)
176179 return (f $ unsafeCoerce x)
177180
178181-- | Convert gathered indices into checks.
0 commit comments