    {-# LANGUAGE ScopedTypeVariables #-}

    module Hedgehog.Classes.Show (showLaws) where

    import Hedgehog
    import Hedgehog.Classes.Common

    -- | Tests the following 'Show' laws:
    --
    -- [__ShowsPrec Zero__]: @'show' a@ ≡ @'showsPrec' 0 a \"\"@
    -- [__ShowsPrec Equivariance__]: @'showsPrec' p a r '++' s@ ≡ @'showsPrec p a (r '++' s)@
    -- [__ShowsPrec ShowList__]: @'showList' as r '++' s@ ≡ @'showList' as (r '++' s)@
    showLaws :: (Show a) => Gen a -> Laws
    showLaws :: forall a. Show a => Gen a -> Laws
    showLaws Gen a
    gen = String -> [(String, Property)] -> Laws
    Laws String
    "Show"
      [ (String
    "ShowsPrec Zero", Gen a -> Property
    forall a. Show a => Gen a -> Property
    showShowsPrecZero Gen a
    gen)
      , (String
    "Equivariance: showsPrec", Gen a -> Property
    forall a. Show a => Gen a -> Property
    equivarianceShowsPrec Gen a
    gen)
      , (String
    "Equivariance: showList", Gen a -> Property
    forall a. Show a => Gen a -> Property
    equivarianceShowList Gen a
    gen)
      ]

    showShowsPrecZero :: forall a. (Show a) => Gen a -> Property
    showShowsPrecZero :: forall a. Show a => Gen a -> Property
    showShowsPrecZero Gen a
    gen = HasCallStack => PropertyT IO () -> Property
    PropertyT IO () -> Property
    property (PropertyT IO () -> Property) -> PropertyT IO () -> Property
    forall a b. (a -> b) -> a -> b
    $ do
      a <- Gen a -> PropertyT IO a
    forall (m :: * -> *) a.
    (Monad m, Show a, HasCallStack) =>
    Gen a -> PropertyT m a
    forAll Gen a
    gen
      let lhs = a -> String
    forall a. Show a => a -> String
    show a
    a
      let rhs = Int -> a -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    0 a
    a String
    ""
      let ctx = LawContext -> Context
    contextualise (LawContext -> Context) -> LawContext -> Context
    forall a b. (a -> b) -> a -> b
    $ LawContext
            { lawContextLawName :: String
    lawContextLawName = String
    "ShowsPrec Zero", lawContextTcName :: String
    lawContextTcName = String
    "Show"
            , lawContextLawBody :: String
    lawContextLawBody = String
    "show a" String -> ShowS
    `congruency` String
    "showsPrec 0 a \"\""
            , lawContextReduced :: String
    lawContextReduced = String -> ShowS
    forall a. Show a => a -> a -> String
    reduced String
    lhs String
    rhs
            , lawContextTcProp :: String
    lawContextTcProp =
                let showA :: String
    showA = a -> String
    forall a. Show a => a -> String
    show a
    a;
                in [String] -> String
    lawWhere
                  [ String
    "show a" String -> ShowS
    `congruency` String
    "showsPrec 0 a \"\", where"
                  , String
    "a = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    showA
                  ]
            }
      heqCtx lhs rhs ctx

    equivarianceShowsPrec :: forall a. (Show a) => Gen a -> Property
    equivarianceShowsPrec :: forall a. Show a => Gen a -> Property
    equivarianceShowsPrec Gen a
    gen = HasCallStack => PropertyT IO () -> Property
    PropertyT IO () -> Property
    property (PropertyT IO () -> Property) -> PropertyT IO () -> Property
    forall a b. (a -> b) -> a -> b
    $ do
      p <- Gen Int -> PropertyT IO Int
    forall (m :: * -> *) a.
    (Monad m, Show a, HasCallStack) =>
    Gen a -> PropertyT m a
    forAll Gen Int
    genShowReadPrecedence
      a <- forAll gen
      r <- forAll genSmallString
      s <- forAll genSmallString
      let lhs = Int -> a -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    p a
    a String
    r String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    s
      let rhs = Int -> a -> ShowS
    forall a. Show a => Int -> a -> ShowS
    showsPrec Int
    p a
    a (String
    r String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    s)
      let ctx = LawContext -> Context
    contextualise (LawContext -> Context) -> LawContext -> Context
    forall a b. (a -> b) -> a -> b
    $ LawContext
            { lawContextLawName :: String
    lawContextLawName = String
    "ShowsPrec Equivariance", lawContextTcName :: String
    lawContextTcName = String
    "Show"
            , lawContextLawBody :: String
    lawContextLawBody = String
    "showsPrec p a r ++ s" String -> ShowS
    `congruency` String
    "showsPrec p a (r ++ s)"
            , lawContextReduced :: String
    lawContextReduced = String -> ShowS
    forall a. Show a => a -> a -> String
    reduced String
    lhs String
    rhs
            , lawContextTcProp :: String
    lawContextTcProp =
                let showP :: String
    showP = Int -> String
    forall a. Show a => a -> String
    show Int
    p; showA :: String
    showA = a -> String
    forall a. Show a => a -> String
    show a
    a; showR :: String
    showR = ShowS
    forall a. Show a => a -> String
    show String
    r; showS :: String
    showS = ShowS
    forall a. Show a => a -> String
    show String
    s;
                in [String] -> String
    lawWhere
                  [ String
    "showsPrec p a r ++ s" String -> ShowS
    `congruency` String
    "showsPrec p a (r ++ s), where"
                  , String
    "p = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    showP
                  , String
    "a = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    showA
                  , String
    "r = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    showR
                  , String
    "s = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    showS
                  ]
            }
      heqCtx lhs rhs ctx

    equivarianceShowList :: forall a. (Show a) => Gen a -> Property
    equivarianceShowList :: forall a. Show a => Gen a -> Property
    equivarianceShowList Gen a
    gen = HasCallStack => PropertyT IO () -> Property
    PropertyT IO () -> Property
    property (PropertyT IO () -> Property) -> PropertyT IO () -> Property
    forall a b. (a -> b) -> a -> b
    $ do
      as <- Gen [a] -> PropertyT IO [a]
    forall (m :: * -> *) a.
    (Monad m, Show a, HasCallStack) =>
    Gen a -> PropertyT m a
    forAll (Gen [a] -> PropertyT IO [a]) -> Gen [a] -> PropertyT IO [a]
    forall a b. (a -> b) -> a -> b
    $ Gen a -> Gen [a]
    forall a. Gen a -> Gen [a]
    genSmallList Gen a
    gen
      r <- forAll genSmallString
      s <- forAll genSmallString
      let lhs = [a] -> ShowS
    forall a. Show a => [a] -> ShowS
    showList [a]
    as String
    r String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    s
      let rhs = [a] -> ShowS
    forall a. Show a => [a] -> ShowS
    showList [a]
    as (String
    r String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    s)
      let ctx = LawContext -> Context
    contextualise (LawContext -> Context) -> LawContext -> Context
    forall a b. (a -> b) -> a -> b
    $ LawContext
            { lawContextLawName :: String
    lawContextLawName = String
    "ShowList Equivariance", lawContextTcName :: String
    lawContextTcName = String
    "Show"
            , lawContextLawBody :: String
    lawContextLawBody = String
    "showList as r ++ s" String -> ShowS
    `congruency` String
    "showList as (r ++ s)"
            , lawContextReduced :: String
    lawContextReduced = String -> ShowS
    forall a. Show a => a -> a -> String
    reduced String
    lhs String
    rhs
            , lawContextTcProp :: String
    lawContextTcProp =
                let showAS :: String
    showAS = [a] -> String
    forall a. Show a => a -> String
    show [a]
    as; showR :: String
    showR = ShowS
    forall a. Show a => a -> String
    show String
    r; showS :: String
    showS = ShowS
    forall a. Show a => a -> String
    show String
    s;
                in [String] -> String
    lawWhere
                  [ String
    "showList as r ++ s" String -> ShowS
    `congruency` String
    "showList as (r ++ s), where"
                  , String
    "as = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    showAS
                  , String
    "r = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    showR
                  , String
    "s = " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ String
    showS
                  ]
            }
      heqCtx lhs rhs ctx