1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE ScopedTypeVariables #-}
module GenericsSpec (main, spec) where
import Data.Functor.Classes
import Data.Proxy (Proxy(..))
import GenericsTypes
import Test.Hspec
import Test.Hspec.QuickCheck (prop)
import Test.QuickCheck (Arbitrary)
import Text.Read (minPrec)
main :: IO ()
main = hspec spec
prop_Eq :: (Eq a, Eq (f a), Eq1 f) => f a -> f a -> Expectation
prop_Eq x y = (x == y) `shouldBe` eq1 x y
eqSpec :: forall f a. (Arbitrary (f a), Show (f a),
Eq a, Eq (f a), Eq1 f)
=> Proxy (f a) -> Spec
eqSpec _ = prop "has a valid Eq1 instance" (prop_Eq :: f a -> f a -> Expectation)
prop_Ord :: (Ord a, Ord (f a), Ord1 f) => f a -> f a -> Expectation
prop_Ord x y = compare x y `shouldBe` compare1 x y
ordSpec :: forall f a. (Arbitrary (f a), Show (f a),
Ord a, Ord (f a), Ord1 f)
=> Proxy (f a) -> Spec
ordSpec _ = prop "has a valid Ord1 instance" (prop_Ord :: f a -> f a -> Expectation)
-- Adapted from the definition of readEither
readEither' :: String -> (Int -> ReadS a) -> Either String a
readEither' s rs =
case [ x | (x,"") <- rs minPrec s ] of
[x] -> Right x
[] -> Left "read': no parse"
_ -> Left "read': ambiguous parse"
read' :: String -> (Int -> ReadS a) -> a
read' s = either error id . readEither' s
prop_Read :: forall f a. (Read a, Read (f a), Read1 f,
Eq (f a), Show (f a))
=> f a -> Expectation
prop_Read x = readArb readsPrec `shouldBe` readArb readsPrec1
where
readArb :: (Int -> ReadS (f a)) -> f a
readArb = read' (show x)
readSpec :: forall f a. (Arbitrary (f a), Eq (f a), Show (f a),
Read a, Read (f a), Read1 f)
=> Proxy (f a) -> Spec
readSpec _ = prop "has a valid Read1 instance" (prop_Read :: f a -> Expectation)
prop_Show :: (Show a, Show (f a), Show1 f) => Int -> f a -> Expectation
prop_Show p x = showsPrec p x "" `shouldBe` showsPrec1 p x ""
showSpec :: forall f a. (Arbitrary (f a), Show a, Show (f a), Show1 f)
=> Proxy (f a) -> Spec
showSpec _ = prop "has a valid Show1 instance" (prop_Show :: Int -> f a -> Expectation)
classes1Spec :: forall f a. (Arbitrary (f a),
Ord a, Ord (f a), Ord1 f,
Read a, Read (f a), Read1 f,
Show a, Show (f a), Show1 f)
=> String -> Proxy (f a) -> Spec
classes1Spec str proxy =
describe str $ do eqSpec proxy
ordSpec proxy
readSpec proxy
showSpec proxy
spec :: Spec
spec = parallel $ do
classes1Spec "TestParam" (Proxy :: Proxy (TestParam Int))
classes1Spec "T#" (Proxy :: Proxy (T# Int))
classes1Spec "Infix" (Proxy :: Proxy (Infix Int))
classes1Spec "GADT" (Proxy :: Proxy (GADT Int))
classes1Spec "Record" (Proxy :: Proxy (Record Int))
describe "Prim" $ do
let proxy :: Proxy (Prim Int)
proxy = Proxy
eqSpec proxy
ordSpec proxy
showSpec proxy
describe "Empty" $ do
let proxy :: Proxy (Empty Int)
proxy = Proxy
eqSpec proxy
ordSpec proxy
it "should fail to parse eagerly" $ do
let readEmpty :: String -> (Int -> ReadS (Empty Int)) -> Either String (Empty Int)
readEmpty = readEither'
readEmpty "" readsPrec `shouldBe` readEmpty "" readsPrec1
readEmpty (error "boom") readsPrec `shouldBe` readEmpty (error "boom") readsPrec1
|