content: -----------------------------------------------------------------------------
  -- |
  -- Module      :  Test.QuickCheck.Utils
  -- Copyright   :  (c) Andy Gill 2001
  -- License     :  BSD-style (see the file libraries/base/LICENSE)
  -- 
  -- Maintainer  :  libraries@haskell.org
  -- Stability   :  experimental
  -- Portability :  portable
  --
  -- These are some general purpose utilities for use with QuickCheck.
  --
  -----------------------------------------------------------------------------
  
  module Test.QuickCheck.Utils
    ( isAssociativeBy
    , isAssociative
    , isCommutableBy
    , isCommutable
    , isTotalOrder
    ) where
  
  import Prelude
  
  import Test.QuickCheck
  
  isAssociativeBy :: (Show a,Testable prop) 
  		=> (a -> a -> prop) -> Gen a -> (a -> a -> a) -> Property
  isAssociativeBy (===) src (**) = 
       	forAll src $ \ a ->
       	forAll src $ \ b ->
       	forAll src $ \ c ->
  	((a ** b) ** c) === (a ** (b ** c))
  
  isAssociative :: (Arbitrary a,Show a,Eq a) => (a -> a -> a) -> Property
  isAssociative = isAssociativeBy (==) arbitrary
  
  isCommutableBy :: (Show a,Testable prop) 
  	       => (b -> b -> prop) -> Gen a -> (a -> a -> b) -> Property
  isCommutableBy (===) src (**) =
  	forAll src $ \ a ->
  	forAll src $ \ b ->
  	(a ** b) === (b ** a)
  
  isCommutable :: (Arbitrary a,Show a,Eq b) => (a -> a -> b) -> Property
  isCommutable = isCommutableBy (==) arbitrary
  
  isTotalOrder :: (Arbitrary a,Show a,Ord a) => a -> a -> Property
  isTotalOrder x y = 
      classify (x > y)  "less than" $
      classify (x == y) "equals" $
      classify (x < y)  "greater than" $
      x < y || x == y || x > y
  