{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

module Test.QuickCheck.HigherOrder.Internal.Testable.Class where

import Test.QuickCheck

import Test.QuickCheck.HigherOrder.Internal.Constructible

-- * An alternative Testable

-- | Types that represent testable properties.
--
-- This is a clone of the 'Testable' class with an improved function instance.
class Testable' prop where
  property' :: prop -> Property

-- * Helpers

-- | Equivalent to 'property'' specialized to functions:
-- convert a function to a 'Property'.
forAll_
  :: forall a prop
  .  (Constructible a, Testable' prop)
  => (a -> prop) -> Property
forAll_ :: (a -> prop) -> Property
forAll_ a -> prop
f =
  Gen (Repr a)
-> (Repr a -> [Repr a])
-> (Repr a -> String)
-> (Repr a -> Property)
-> Property
forall prop a.
Testable prop =>
Gen a -> (a -> [a]) -> (a -> String) -> (a -> prop) -> Property
forAllShrinkShow
    (Arbitrary (Repr a) => Gen (Repr a)
forall a. Arbitrary a => Gen a
arbitrary @(Repr a))
    (Arbitrary (Repr a) => Repr a -> [Repr a]
forall a. Arbitrary a => a -> [a]
shrink    @(Repr a))
    (Show (Repr a) => Repr a -> String
forall a. Show a => a -> String
show      @(Repr a))
    (prop -> Property
forall prop. Testable' prop => prop -> Property
property' (prop -> Property) -> (Repr a -> prop) -> Repr a -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> prop
f (a -> prop) -> (Repr a -> a) -> Repr a -> prop
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Repr a -> a
forall a. Constructible a => Repr a -> a
fromRepr)

-- | A 'Property' is the canonical type of testable properties.
--
-- > property' @Property = property @Property = id
instance Testable' Property where
  property' :: Property -> Property
property' = Property -> Property
forall a. a -> a
id

instance Testable' Bool where
  property' :: Bool -> Property
property' = Bool -> Property
forall prop. Testable prop => prop -> Property
property

-- | A generator represents a universally quantified property.
instance Testable' a => Testable' (Gen a) where
  property' :: Gen a -> Property
property' = Gen Property -> Property
forall prop. Testable prop => prop -> Property
property (Gen Property -> Property)
-> (Gen a -> Gen Property) -> Gen a -> Property
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Property) -> Gen a -> Gen Property
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Property
forall prop. Testable' prop => prop -> Property
property'

-- | A function represents a universally quantified property.
instance (Constructible a, Testable' b) => Testable' (a -> b) where
  property' :: (a -> b) -> Property
property' = (a -> b) -> Property
forall a b. (Constructible a, Testable' b) => (a -> b) -> Property
forAll_