packages feed

HMock 0.5.0.0 → 0.5.1.0

raw patch · 11 files changed

+192/−89 lines, 11 filesdep ~basedep ~mtldep ~template-haskellPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base, mtl, template-haskell

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,12 @@ # Revision history for hmock +## 0.5.1.0 -- 2021-09-25++* HMock works with more classes with superclass constraints.+* Classes with default methods are now fully mockable.+* Builds with GHC 9.2.1+* Fixes for GHC 8.4 and 8.6+ ## 0.5.0.0 -- 2021-09-25 * HMock now depends on `Predicate` from the `explainable-predicates` package. 
HMock.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               HMock-version:            0.5.0.0+version:            0.5.1.0 synopsis:           A flexible mock framework for testing effectful code. description:        HMock is a flexible mock framework for testing effectful                     code in Haskell.  Tests can set up expectations about@@ -42,7 +42,7 @@                       Test.HMock.Internal.Step,                       Test.HMock.Internal.TH,                       Test.HMock.Internal.Util-    build-depends:    base >=4.11.0 && < 4.16,+    build-depends:    base >=4.11.0 && < 4.17,                       constraints >= 0.13 && < 0.14,                       containers >= 0.6.2 && < 0.7,                       data-default >= 0.7.1 && < 0.8,@@ -53,7 +53,7 @@                       mtl >= 2.2.2 && < 2.3,                       stm >= 2.5.0 && < 2.6,                       syb >= 0.7.2 && < 0.8,-                      template-haskell >= 2.14 && < 2.18,+                      template-haskell >= 2.14 && < 2.19,                       transformers-base >= 0.4.5 && < 0.5,                       unliftio >= 0.2.18 && < 0.3,     hs-source-dirs:   src
src/Test/HMock.hs view
@@ -34,7 +34,7 @@ -- copyFile :: MonadFilesystem m => 'FilePath' -> 'FilePath' -> m () -- copyFile a b = readFile a >>= writeFile b ----- 'Test.HMock.TH.makeMockable' ''MonadFilesystem+-- 'Test.HMock.TH.makeMockable' [t|MonadFilesystem|] -- -- spec = describe "copyFile" '$' --   it "reads a file and writes its contents to another file" '$'
src/Test/HMock/Internal/State.hs view
@@ -36,7 +36,7 @@ import Test.HMock.Mockable (Mockable (..)) import UnliftIO   ( MonadIO,-    MonadUnliftIO,+    MonadUnliftIO(withRunInIO),     STM,     TVar,     atomically,@@ -198,12 +198,16 @@       MonadBase b,       MonadCatch,       MonadMask,-      MonadThrow,-      MonadUnliftIO+      MonadThrow     )  instance MonadTrans MockT where   lift = MockT . lift++-- Note: The 'MonadUnliftIO' instance is implemented manually because deriving+-- it causes compilation failure in GHC 8.6 and 8.8.  (See issue #23.)+instance MonadUnliftIO m => MonadUnliftIO (MockT m) where+  withRunInIO inner = MockT $ withRunInIO $ \run -> inner (run . unMockT)  -- | Applies a function to the base monad of 'MockT'. mapMockT :: (m a -> m b) -> MockT m a -> MockT m b
src/Test/HMock/Internal/TH.hs view
@@ -24,14 +24,13 @@   ) where -import Control.Monad.Extra (mapMaybeM)+import Control.Monad.Extra (mapMaybeM, concatMapM) import Data.Generics-import Data.List ((\\))+import Data.List ((\\), nub) import Data.Maybe (catMaybes, fromMaybe) import Language.Haskell.TH import Language.Haskell.TH.Syntax (NameFlavour (..)) import Test.HMock.Internal.Util (choices)-import Data.Foldable (foldl')  #if MIN_VERSION_template_haskell(2,17,0) @@ -188,50 +187,53 @@ -- | Attempts to produce sufficient constraints for the given 'Type' to be an -- instance of the given class 'Name'. resolveInstance :: Name -> [Type] -> Q (Maybe Cxt)-resolveInstance cls args-  | all isTypeVar args = return (Just [foldl' AppT (ConT cls) args])-  where-    isTypeVar :: Type -> Bool-    isTypeVar (VarT _) = True-    isTypeVar _ = False resolveInstance cls args = do   decs <- reifyInstances cls args-  result <- traverse (tryInstance args) decs-  case catMaybes result of-    [cx] -> return (Just (filter (not . null . freeTypeVars) cx))+  results <- catMaybes <$> traverse (tryInstance args) decs+  case results of+    [cx] -> pure (Just cx)     _ -> return Nothing   where     tryInstance :: [Type] -> InstanceDec -> Q (Maybe Cxt)     tryInstance actualArgs (InstanceD _ cx instType _) =       case splitTypeApp instType of-        Just (cls', instArgs) | cls' == cls ->-          unifyWithin [] instArgs actualArgs >>= \case-            Just tbl ->-              let cx' = substTypeVars tbl <$> cx-              in fmap concat . sequence <$> mapM resolveInstanceType cx'-            Nothing -> return Nothing+        Just (cls', instArgs)+          | cls' == cls ->+            unifyWithin [] instArgs actualArgs >>= \case+              Just tbl -> simplifyContext (substTypeVars tbl <$> cx)+              Nothing -> return Nothing         _ -> return Nothing     tryInstance _ _ = return Nothing  -- | Attempts to produce sufficient constraints for the given 'Type' to be a -- satisfied constraint.  The type should be a class applied to its type -- parameters.+--+-- Unlike 'simplifyContext', this function always resolves the top-level+-- constraint, and returns 'Nothing' if it cannot do so. resolveInstanceType :: Type -> Q (Maybe Cxt)-resolveInstanceType t = case splitTypeApp t of-  Just (cls, args) -> resolveInstance cls args-  Nothing -> return Nothing+resolveInstanceType t =+  maybe (pure Nothing) (uncurry resolveInstance) (splitTypeApp t)  -- | Simplifies a context with complex types (requiring FlexibleContexts) to try -- to obtain one with all constraints applied to variables.+--+-- Should return Nothing if and only if the simplified contraint is+-- unsatisfiable, which is the case if and only if it contains a component with+-- no type variables. simplifyContext :: Cxt -> Q (Maybe Cxt)-simplifyContext (p : preds) =-  case splitTypeApp p of-    Just (cls, args) ->-      resolveInstance cls args >>= \case-        Just cxt' -> fmap (cxt' ++) <$> simplifyContext preds-        Nothing -> return Nothing-    _ -> fmap (p :) <$> simplifyContext preds-simplifyContext [] = return (Just [])+simplifyContext preds+  | all isVarApp preds = return (Just preds)+  | otherwise = do+    let simplifyPred t = fromMaybe [t] <$> resolveInstanceType t+    components <- concatMapM simplifyPred preds+    if any (null . freeTypeVars) components+      then return Nothing+      else return (Just (nub components))+  where+    isVarApp (ConT _) = True+    isVarApp (AppT t (VarT _)) | isVarApp t = True+    isVarApp _ = False  -- | Remove instance context from a method. --
src/Test/HMock/TH.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-}-{-# LANGUAGE ExplicitNamespaces #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TemplateHaskell #-}@@ -177,7 +176,7 @@   [Dec] ->   Q Instance makeInstance options ty cx tbl ps m members = do-  processedMembers <- mapM (getMethod ty m tbl) members+  processedMembers <- mapM (getMethod ty m tbl) $ filter isRelevantMember members   (extraMembers, methods) <-     partitionEithers <$> zipWithM memberOrMethod members processedMembers   return $@@ -190,6 +189,10 @@         instExtraMembers = extraMembers       }   where+    isRelevantMember :: Dec -> Bool+    isRelevantMember DefaultSigD {} = False+    isRelevantMember _ = True+     memberOrMethod :: Dec -> Either [String] Method -> Q (Either Dec Method)     memberOrMethod dec (Left warnings) = do       when (mockVerbose options) $ mapM_ reportWarning warnings@@ -620,12 +623,8 @@     argCxt :: Type -> Q (Maybe Cxt)     argCxt argTy       | not (isKnownType method argTy) = return Nothing-      | VarT v <- argTy =-        Just <$> sequence [[t|Eq $(varT v)|], [t|Show $(varT v)|]]-      | otherwise = do-        eqCxt <- resolveInstance ''Eq [argTy]-        showCxt <- resolveInstance ''Show [argTy]-        return ((++) <$> eqCxt <*> showCxt)+      | otherwise =+        simplifyContext [AppT (ConT ''Eq) argTy, AppT (ConT ''Show) argTy]  deriveForMockT :: MakeMockableOptions -> Type -> Q [Dec] deriveForMockT options ty = do@@ -660,8 +659,12 @@                    AppT (ConT ''MonadIO) (VarT (instMonadVar inst))                  ] -      simplifyContext-        (substTypeVar (instMonadVar inst) (AppT (ConT ''MockT) (VarT m)) <$> cx)+      let mockTConstraints =+            substTypeVar+              (instMonadVar inst)+              (AppT (ConT ''MockT) (VarT m))+              <$> cx+      simplifyContext mockTConstraints         >>= \case           Just cxMockT ->             (: [])@@ -689,7 +692,7 @@     actionExp (v : vs) e = actionExp vs [|$e $(varE v)|]      body argVars = do-      defaultCxt <- resolveInstance ''Default [methodResult method]+      defaultCxt <- simplifyContext [AppT (ConT ''Default) (methodResult method)]       let someMockMethod = case defaultCxt of             Just [] -> [|mockMethod|]             _ -> [|mockDefaultlessMethod|]
test/Classes.hs view
@@ -1,7 +1,9 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-}+{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-}@@ -17,11 +19,13 @@ module Classes where  import Control.DeepSeq (NFData (rnf))-import Control.Exception (evaluate)+import Control.Exception (SomeException, evaluate)+import Control.Monad.Reader (MonadReader) import Control.Monad.Trans (MonadIO, liftIO) import Data.Default (Default (def)) import Data.Dynamic (Typeable) import Data.Kind (Type)+import Data.List (isInfixOf) import Language.Haskell.TH.Syntax hiding (Type) import QuasiMock import Test.HMock@@ -36,6 +40,9 @@  deriveRecursive (Just AnyclassStrategy) ''NFData ''Dec +anyQMonadFailure :: SomeException -> Bool+anyQMonadFailure e = "(Q monad failure)" `isInfixOf` show e+ class MonadSimple m where   simple :: String -> m () @@ -69,7 +76,7 @@             _ <- runQ (makeMockable [t|MonadSimple|])             return () -      missingGADTs `shouldThrow` anyException+      missingGADTs `shouldThrow` anyQMonadFailure    it "fails when TypeFamilies is disabled" $     example $ do@@ -80,7 +87,7 @@             _ <- runQ (makeMockable [t|MonadSimple|])             return () -      missingTypeFamilies `shouldThrow` anyException+      missingTypeFamilies `shouldThrow` anyQMonadFailure    it "fails when DataKinds is disabled" $     example $ do@@ -91,7 +98,7 @@             _ <- runQ (makeMockable [t|MonadSimple|])             return () -      missingDataKinds `shouldThrow` anyException+      missingDataKinds `shouldThrow` anyQMonadFailure    it "fails when FlexibleInstances is disabled" $     example $ do@@ -103,7 +110,7 @@             _ <- runQ (makeMockable [t|MonadSimple|])             return () -      missingDataKinds `shouldThrow` anyException+      missingDataKinds `shouldThrow` anyQMonadFailure    it "fails when MultiParamTypeClasses is disabled" $     example $ do@@ -117,7 +124,7 @@             _ <- runQ (makeMockable [t|MonadSimple|])             return () -      missingDataKinds `shouldThrow` anyException+      missingDataKinds `shouldThrow` anyQMonadFailure    it "fails when ScopedTypeVariables is disabled" $     example $ do@@ -131,11 +138,12 @@             _ <- runQ (makeMockable [t|MonadSimple|])             return () -      missingDataKinds `shouldThrow` anyException+      missingDataKinds `shouldThrow` anyQMonadFailure    it "fails when too many params are given" $     example $ do       let tooManyParams = runMockT $ do+            allowUnexpected $ QReifyInstances_ anything anything |-> []             $(onReify [|expectAny|] ''MonadSimple)             expect $               QReport_ anything (hasSubstr "is applied to too many arguments")@@ -143,7 +151,7 @@             _ <- runQ (makeMockable [t|MonadSimple IO|])             return () -      tooManyParams `shouldThrow` anyException+      tooManyParams `shouldThrow` anyQMonadFailure    it "is mockable" $     example $ do@@ -271,6 +279,36 @@       success       failure `shouldThrow` anyException +class MonadReader String m => MonadPassThroughSuper m where+  withPassThroughSuper :: m ()++makeMockable [t|MonadPassThroughSuper|]++passThroughSuperTests :: SpecWith ()+passThroughSuperTests = describe "MonadPassThroughSuper" $ do+  it "generates mock impl" $+    example $ do+      decs <- runMockT $ do+        allowUnexpected $ QReifyInstances_ anything anything |-> []+        $(onReify [|expectAny|] ''MonadPassThroughSuper)+        expectAny $+          QReifyInstances_+            (eq ''MonadReader)+            $( qMatch+                 [p|+                   [ VarT _,+                     AppT (ConT (Name (OccName "MockT") _)) (VarT _)+                     ]+                   |]+             )+            |-> $( reifyInstancesStatic+                     ''MonadReader+                     [VarT (mkName "r"), AppT (ConT ''MockT) (VarT (mkName "v"))]+                 )++        runQ (makeMockable [t|MonadPassThroughSuper|])+      evaluate (rnf decs)+ class MonadMPTC a m where   mptc :: a -> m ()   mptcList :: [a] -> m ()@@ -429,6 +467,7 @@   it "fails without RankNTypes" $     example $ do       let missingRankNTypes = runMockT $ do+            allowUnexpected $ QReifyInstances_ anything anything |-> []             $(onReify [|expectAny|] ''MonadPolyArg)             expectAny $ QIsExtEnabled RankNTypes |-> False             expect $@@ -437,7 +476,7 @@             _ <- runQ (makeMockable [t|MonadPolyArg|])             return () -      missingRankNTypes `shouldThrow` anyException+      missingRankNTypes `shouldThrow` anyQMonadFailure    it "is mockable" $     example $ do@@ -543,6 +582,33 @@       x <- polyResult (3 :: Int)       liftIO $ x `shouldBe` 3 +class MonadDefaultSignatures m where+  methodWithDefault :: Int -> m Int+  default methodWithDefault :: MonadIO m => Int -> m Int+  methodWithDefault = liftIO . methodWithDefault++instance MonadDefaultSignatures IO where+  methodWithDefault = pure++makeMockable [t|MonadDefaultSignatures|]++defaultSignaturesTests :: SpecWith ()+defaultSignaturesTests = describe "MonadDefaultSignatures" $ do+  it "generates mock impl" $+    example $ do+      decs <- runMockT $ do+        allowUnexpected $ QReifyInstances_ anything anything |-> []+        $(onReify [|expectAny|] ''MonadDefaultSignatures)+        runQ (makeMockable [t|MonadDefaultSignatures|])+      evaluate (rnf decs)+  it "is mockable" $+    example . runMockT $ do+      expect $+        MethodWithDefault_ anything+          |=> \MethodWithDefault {} -> return 42+      x <- methodWithDefault 0+      liftIO $ x `shouldBe` 42+ class MonadExtraneousMembers m where   data SomeDataType m   favoriteNumber :: SomeDataType m -> Int@@ -612,6 +678,7 @@   it "fails to derive MockT when class has extra methods" $     example $ do       let unmockableMethods = runMockT $ do+            allowUnexpected $ QReifyInstances_ anything anything |-> []             $(onReify [|expectAny|] ''MonadExtraneousMembers)             expect $               QReport_ anything (hasSubstr "has unmockable methods")@@ -619,7 +686,7 @@             _ <- runQ (makeMockable [t|MonadExtraneousMembers|])             return () -      unmockableMethods `shouldThrow` anyException+      unmockableMethods `shouldThrow` anyQMonadFailure    it "is mockable" $     example $ do@@ -682,7 +749,7 @@         decs <- runMockT $ do           allowUnexpected $ QReifyInstances_ anything anything |-> []           $(onReify [|expectAny|] ''MonadManyReturns)-          $(onReifyInstances [|expectAny|] ''Default [ConT ''NoDefault])+          $(onReifyInstances [|expectAny|] ''Default [[t|NoDefault|]])            runQ (makeMockable [t|MonadManyReturns|])         evaluate (rnf decs)@@ -738,10 +805,8 @@       decs <- runMockT $ do         allowUnexpected $ QReifyInstances_ anything anything |-> []         $(onReify [|expectAny|] ''MonadNestedNoDef)-        $( [t|(NoDefault, String)|]-             >>= onReifyInstances [|expectAny|] ''Default . (: [])-         )-        $(onReifyInstances [|expectAny|] ''Default [ConT ''NoDefault])+        $(onReifyInstances [|expectAny|] ''Default [[t|(NoDefault, String)|]])+        $(onReifyInstances [|expectAny|] ''Default [[t|NoDefault|]])          runQ (makeMockable [t|MonadNestedNoDef|])       evaluate (rnf decs)@@ -763,7 +828,7 @@             _ <- runQ (makeMockable [t|Int|])             return () -      wrongKind `shouldThrow` anyException+      wrongKind `shouldThrow` anyQMonadFailure    it "fails when given an unexpected type constructor" $     example $ do@@ -773,7 +838,7 @@             _ <- runQ (makeMockable [t|(Int, String)|])             return () -      notClass `shouldThrow` anyException+      notClass `shouldThrow` anyQMonadFailure    it "fails when class has no params" $     example $ do@@ -787,7 +852,7 @@             _ <- runQ (makeMockable [t|ClassWithNoParams|])             return () -      tooManyParams `shouldThrow` anyException+      tooManyParams `shouldThrow` anyQMonadFailure    it "fails when class has no mockable methods" $     example $ do@@ -797,7 +862,7 @@             _ <- runQ (makeMockable [t|Show|])             return () -      noMockableMethods `shouldThrow` anyException+      noMockableMethods `shouldThrow` anyQMonadFailure  classTests :: SpecWith () classTests = describe "makeMockable" $ do@@ -805,6 +870,7 @@   suffixTests   setupTests   superTests+  passThroughSuperTests   mptcTests   fdSpecializedTests   fdGeneralTests@@ -812,6 +878,7 @@   polyArgTests   unshowableArgTests   monadInArgTests+  defaultSignaturesTests   extraneousMembersTests   rankNTests   defaultReturnTests
test/Demo.hs view
@@ -3,7 +3,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TemplateHaskell #-}
test/QuasiMock.hs view
@@ -51,6 +51,11 @@   qRecover = error "qRecover"   qReifyAnnotations = error "qReifyAnnotations" +#if MIN_VERSION_template_haskell(2, 18, 0)+  qGetDoc l = mockMethod (QGetDoc l)+  qPutDoc l s = mockMethod (QPutDoc l s)+#endif+ functionType :: [Type] -> Bool functionType = everything (||) (mkQ False isArrow)   where@@ -68,25 +73,32 @@     $(onReify [|allowUnexpected|] ''Enum)     $(onReify [|allowUnexpected|] ''Monad) -    $(onReifyInstances [|allowUnexpected|] ''Show [ConT ''String])-    $(onReifyInstances [|allowUnexpected|] ''Eq [ConT ''String])-    $(onReifyInstances [|allowUnexpected|] ''Show [ConT ''Char])-    $(onReifyInstances [|allowUnexpected|] ''Eq [ConT ''Char])-    $(onReifyInstances [|allowUnexpected|] ''Show [ConT ''Int])-    $(onReifyInstances [|allowUnexpected|] ''Eq [ConT ''Int])-    $(onReifyInstances [|allowUnexpected|] ''Show [ConT ''Bool])-    $(onReifyInstances [|allowUnexpected|] ''Eq [ConT ''Bool])-    $(onReifyInstances [|allowUnexpected|] ''Default [TupleT 0])-    $(onReifyInstances [|allowUnexpected|] ''Default [ConT ''String])-    $(onReifyInstances [|allowUnexpected|] ''Default [ConT ''Int])-    $( onReifyInstances-         [|allowUnexpected|]-         ''Default-         [AppT (ConT ''Maybe) (ConT ''Bool)]-     )+    $(onReifyInstances [|allowUnexpected|] ''Show [[t|String|]])+    $(onReifyInstances [|allowUnexpected|] ''Eq [[t|String|]])+    $(onReifyInstances [|allowUnexpected|] ''Show [[t|Char|]])+    $(onReifyInstances [|allowUnexpected|] ''Eq [[t|Char|]])+    $(onReifyInstances [|allowUnexpected|] ''Show [[t|Int|]])+    $(onReifyInstances [|allowUnexpected|] ''Eq [[t|Int|]])+    $(onReifyInstances [|allowUnexpected|] ''Show [[t|Bool|]])+    $(onReifyInstances [|allowUnexpected|] ''Eq [[t|Bool|]])+    $(onReifyInstances [|allowUnexpected|] ''Default [[t|()|]])+    $(onReifyInstances [|allowUnexpected|] ''Default [[t|String|]])+    $(onReifyInstances [|allowUnexpected|] ''Default [[t|Int|]])+    $(onReifyInstances [|allowUnexpected|] ''Default [[t|Maybe Bool|]])      allowUnexpected $ QReifyInstances_ (eq ''Show) (is functionType) |-> []     allowUnexpected $ QReifyInstances_ (eq ''Eq) (is functionType) |-> []++    allowUnexpected $+      QReifyInstances_+        (eq ''Show)+        (elemsAre [$(qMatch [p|VarT _|])])+        |-> $(reifyInstancesStatic ''Show [VarT (mkName "a")])+    allowUnexpected $+      QReifyInstances_+        (eq ''Eq)+        (elemsAre [$(qMatch [p|VarT _|])])+        |-> $(reifyInstancesStatic ''Eq [VarT (mkName "a")])      allowUnexpected $       QReifyInstances_
test/QuasiMockBase.hs view
@@ -46,7 +46,8 @@ reifyInstancesStatic :: Name -> [Type] -> Q Exp reifyInstancesStatic n ts = reifyInstances n ts >>= lift -onReifyInstances :: Q Exp -> Name -> [Type] -> Q Exp-onReifyInstances handler n ts = do+onReifyInstances :: Q Exp -> Name -> [Q Type] -> Q Exp+onReifyInstances handler n qts = do+  ts <- sequence qts   result <- reifyInstances n ts   [|$handler (QReifyInstances $(lift n) $(lift ts) |-> $(lift result))|]
test/TH.hs view
@@ -10,9 +10,12 @@ import Test.HMock import Test.HMock.Internal.TH (resolveInstance, unifyTypes) import Test.Hspec+import Test.Predicates (anything, eq)  data NotShowable +class NoInstances a+ $(pure [])  thUtilSpec :: SpecWith ()@@ -49,6 +52,13 @@           liftIO $ result `shouldBe` Just [(v, ConT ''Char)]    describe "resolveInstance" $ do+    it "fails for missing instances" $+      example $+        runMockT $ do+          allowUnexpected $ QReifyInstances_ (eq ''NoInstances) anything |-> []+          result <- runQ $ resolveInstance ''NoInstances [ConT ''String]+          liftIO $ result `shouldBe` Nothing+     it "finds unrestricted instances" $       example $         runMockT $ do@@ -66,10 +76,8 @@       example $         runMockT $ do           $(onReify [|expectAny|] ''NotShowable)-          $(onReifyInstances [|expectAny|] ''Show [ConT ''NotShowable])-          $( [t|(Int, NotShowable)|]-               >>= onReifyInstances [|expectAny|] ''Show . (: [])-           )+          $(onReifyInstances [|expectAny|] ''Show [[t|NotShowable|]])+          $(onReifyInstances [|expectAny|] ''Show [[t|(Int, NotShowable)|]])            t <- runQ [t|(Int, NotShowable)|]           result <- runQ $ resolveInstance ''Show [t]