Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix String instance and add prop tests #17

Merged
merged 1 commit into from
Nov 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions src/Data/Text/Display.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ import Data.List.NonEmpty
import Data.Text (Text)
import Data.Text.Lazy.Builder (Builder)
import Data.Word
import GHC.Show (showLitString)
import GHC.TypeLits
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text.Lazy.Builder as TB
import qualified Data.Text.Lazy.Builder.Int as TB
import qualified Data.Text.Lazy.Builder.RealFloat as TB
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Proxy

Expand All @@ -67,13 +67,12 @@ class Display a where
--
-- === Example
--
-- > import qualified Data.Text.Lazy.Builder as TB
-- >
-- > instance Display Char where
-- > displayBuilder '\'' = "'\\''"
-- > displayBuilder c = "'" <> TB.singleton c <> "\'"
-- > -- 'displayList' is overloaded, so that when the @Display [a]@ instance calls 'displayList',
-- > -- we end up with a nice string enclosed between double quotes.
-- > displayList cs = TB.fromString $ "\"" <> showLitString cs "\""
--
-- > displayBuilder c = TB.fromText $ T.singleton c
-- > displayList cs = TB.fromText $ T.pack cs
-- >
-- > instance Display a => Display [a] where
-- > -- In this instance, 'displayBuilder' is defined in terms of 'displayList', which for most types
-- > -- is defined as the default written in the class declaration.
Expand Down Expand Up @@ -274,12 +273,19 @@ deriving via (ShowInstance ()) instance Display ()
deriving via (ShowInstance Bool) instance Display Bool

-- | @since 0.0.1.0
-- 'displayList' is overloaded, so that when the @Display [a]@ instance calls 'displayList',
-- we end up with a nice string instead of a list of chars between brackets.
--
-- >>> display [1, 2, 3]
-- "[1,2,3]"
--
-- >>> display ['h', 'e', 'l', 'l', 'o']
-- "hello"
instance Display Char where
Kleidukos marked this conversation as resolved.
Show resolved Hide resolved
displayBuilder '\'' = "'\\''"
displayBuilder c = "'" <> TB.singleton c <> "\'"
-- 'displayList' is overloaded, so that when the @Display [a]@ instance calls 'displayList',
-- we end up with a nice string enclosed between double quotes.
displayList cs = TB.fromString $ "\"" <> showLitString cs "\""
-- This instance's implementation is used in the haddocks of the typeclass.
-- If you change it, reflect the change in the documentation.
displayBuilder c = TB.fromText $ T.singleton c
displayList cs = TB.fromText $ T.pack cs

-- | Lazy 'TL.Text'
--
Expand Down
33 changes: 21 additions & 12 deletions test/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ module Main where

import Data.ByteString
import Data.List.NonEmpty
import Data.Text (Text)
import Test.Hspec
import Test.Hspec.QuickCheck
import Data.Text.Arbitrary
import Test.ShouldNotTypecheck (shouldNotTypecheck)
import qualified Data.List.NonEmpty as NE
import qualified Data.Text as T
Expand All @@ -34,7 +35,7 @@ data OpaqueType = OpaqueType Int

spec :: Spec
spec = do
describe "Display Tests" $ 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" $
Expand All @@ -59,28 +60,36 @@ spec = do
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 "Char '\'' instance is equivalent to Text" $ do
display '\'' `shouldBe` T.singleton '\''
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
display tuple `shouldBe` "(" <> display (1 :: Int) <> "," <> display True <> "," <> display @String "hahahha" <> ")"

describe "Display props:" $ do
prop "Text instance stays the same" $ do
\string -> display (string :: Text) `shouldBe` string
prop "String instance is equivalent to Text" $ do
\string -> display (string :: String) `shouldBe` T.pack string
prop "Chars are packed" $
\c -> display (c :: Char) `shouldBe` T.singleton c

describe "Forbidden instances" $ do
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" $
it "Surrounds with parens when True" $
displayParen True "foo" `shouldBe` "(foo)"
it "doesn't surround with parens when False" $
it "Doesn't surround with parens when False" $
displayParen False "foo" `shouldBe` "foo"
it "Surrounds deeply-nested Maybes with a prec of 10" $
displayPrec 10 (Just (Just (Just (3 :: Int)))) `shouldBe` "Just (Just (Just 3))"
it "Surrounds deeply-nested Maybes with a prec of 11" $
displayPrec 11 (Just (Just (Just (3 :: Int)))) `shouldBe` "(Just (Just (Just 3)))"
1 change: 1 addition & 0 deletions text-display.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@ test-suite text-display-test
, hspec
, text
, should-not-typecheck
, quickcheck-text