-----------------------------------------------------------------------------
-- |
-- Module      :  Generics.Putlenses.QuickCheck
-- Copyright   :  (C) 2013 Hugo Pacheco
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Hugo Pacheco <hpacheco@nii.ac.jp>
-- Stability   :  provisional
--
-- Quickcheck procedures to test the well-behavedness of partial lenses (and therefore putlenses)
-- 
--
--
----------------------------------------------------------------------------
module Generics.Putlenses.QuickCheck where

import Test.QuickCheck
import Generics.Putlenses.Putlens
import Control.Monad.Identity
	
-- | QuickCheck procedure to test if a lens is well-behaved (partial).
wb :: (Eq s,Eq v) => Lens s v -> s -> v -> Property
wb l s v = putgetPartial (\s v -> True) l s v .&&. getputPartial (\s -> True) l s

-- | QuickCheck procedure to test if a lens is well-behaved, taking as arguments particular domains for get and for put (partial).
wbPartial :: (Eq s,Eq v) => (s -> Bool) -> (s -> v -> Bool) -> Lens s v -> s -> v -> Property
wbPartial getDom putDom l s v = putgetPartial putDom l s v .&&. getputPartial getDom l s

-- | QuickCheck procedure to test if a lens satisfies the PutGet law (partial).
putgetPartial :: Eq v => (s -> v -> Bool) -> Lens s v -> s -> v -> Property
putgetPartial putDom l s v = putDom s v ==> get l (runIdentity $ put l s v) == v

-- | QuickCheck procedure to test if a lens satisfies the PutGet law (partial).
getputPartial :: Eq s => (s -> Bool) -> Lens s v -> s -> Property
getputPartial getDom l s = getDom s ==> runIdentity (put l s (get l s)) == s