{-# LANGUAGE DerivingVia #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE DataKinds #-} {-# OPTIONS_GHC -fdefer-type-errors -Wno-deferred-type-errors #-} module Main where import Data.ByteString import Data.List.NonEmpty import Data.Text (Text) import Test.Hspec import Test.ShouldNotTypecheck (shouldNotTypecheck) import qualified Data.List.NonEmpty as NE import qualified Data.Text as T import Data.Text.Display main :: IO () main = hspec spec data AutomaticallyDerived = AD deriving stock Show deriving Display via (ShowInstance AutomaticallyDerived) data ManualType = MT Int instance Display ManualType where displayPrec prec (MT i) = displayParen (prec > 10) $ "MT " <> displayPrec 11 i data OpaqueType = OpaqueType Int deriving Display via (OpaqueInstance "" OpaqueType) spec :: Spec spec = do describe "Display Tests" $ do it "Display instance for Text stays the same" $ display ("3" :: Text) `shouldBe` ("3" :: Text) it "Deriving via its own Show instance works" $ T.unpack (display AD) `shouldBe` show AD it "Opaque types stay opaque" $ display (OpaqueType 3 :: OpaqueType) `shouldBe` "" it "Manual instance is stays the same" $ display (MT 32) `shouldBe` "MT 32" it "List instance is equivalent to Show" $ do let list = [1 .. 5] :: [Int] T.unpack (display list) `shouldBe` show list it "Single-element List instance is equivalent to Show" $ do let list = [1] :: [Int] T.unpack (display list) `shouldBe` show list it "NonEmpty instance is equivalent to Show" $ do let ne = NE.fromList [1 .. 5] :: NonEmpty Int T.unpack (display ne) `shouldBe` show ne it "Just True instance is equivalent to Show" $ do T.unpack (display (Just True)) `shouldBe` show (Just True) it "Nested Maybe instance is equivalent to Show" $ do let nestedMaybe = Just (Just 5) :: Maybe (Maybe Int) T.unpack (display nestedMaybe) `shouldBe` show nestedMaybe it "Nothing instance is equivalent to Show" $ do T.unpack (display (Nothing @Bool)) `shouldBe` show (Nothing @Bool) it "String instance is equivalent to Show" $ do let string = "Bonjour \"tout le monde\" !" :: String T.unpack (display string) `shouldBe` show string it "Char 'c' instance is equivalent to Show" $ do T.unpack (display 'c') `shouldBe` show 'c' it "Char '\'' instance is equivalent to Show" $ do T.unpack (display '\'') `shouldBe` show '\'' it "2-Tuple instance is equivalent to Show" $ do let tuple = (1 :: Int, True) T.unpack (display tuple) `shouldBe` show tuple it "3-Tuple instance is equivalent to Show" $ do let tuple = (1 :: Int, True, "hahahha" :: String) T.unpack (display tuple) `shouldBe` show tuple it "Should not compile for a function instance" $ shouldNotTypecheck (display id) `shouldThrow` anyErrorCall it "Should not compile for ByteStrings" $ let bs = "badstring" :: ByteString in shouldNotTypecheck (display bs) `shouldThrow` anyErrorCall describe "displayParen tests" $ do it "surrounds with parens when True" $ displayParen True "foo" `shouldBe` "(foo)" it "doesn't surround with parens when False" $ displayParen False "foo" `shouldBe` "foo"