hedgehog-optics-1.0.0.3: src/Hedgehog/Optics.hs
module Hedgehog.Optics
( wellFormedPrism,
wellFormedLens,
wellFormedIso,
prismExample,
)
where
import Control.Monad (Monad (return))
import Data.Either (Either (Left, Right))
import Data.Eq (Eq)
import Data.Function ((.))
import Data.Maybe (Maybe (Just))
import Hedgehog (Gen, PropertyT, annotate, forAll, (===))
import Optics.AffineFold (preview)
import Optics.AffineTraversal (matching)
import Optics.Getter (view)
import Optics.Iso (Iso')
import Optics.Lens (Lens')
import Optics.Prism (Prism')
import Optics.Review (review)
import Optics.Setter (set)
import Text.Show (Show)
-- | Checks whether a prism respects the well-formedness
-- laws given in "Optics.Prism"
wellFormedPrism ::
Monad m =>
(Show large, Eq large) =>
(Show small, Eq small) =>
Gen large ->
Gen small ->
-- | Prism signifying that the @small@ type
-- is a subset of the @large@ type -}
Prism' large small ->
PropertyT m ()
wellFormedPrism genLarge genSmall o = do
getSetPrismLaw genLarge o
setGetPrismLaw genSmall o
getSetPrismLaw ::
Monad m =>
(Show large, Eq large) =>
(Show small, Eq small) =>
Gen large ->
Prism' large small ->
PropertyT m ()
getSetPrismLaw genLarge o = do
large <- forAll genLarge
case matching o large of
Right small -> do
annotate "The get-set law must hold for a Prism"
review o small === large
Left _ -> return ()
setGetPrismLaw ::
Monad m =>
(Show large, Eq large) =>
(Show small, Eq small) =>
Gen small ->
Prism' large small ->
PropertyT m ()
setGetPrismLaw genSmall o = do
small <- forAll genSmall
annotate "The set-get law must hold for a Prism"
matching o (review o small) === Right small
-- | Checks whether a lens respects the well-formedness
-- laws given in "Optics.Lens"
wellFormedLens ::
Monad m =>
(Show large, Eq large) =>
(Show small, Eq small) =>
Gen large ->
Gen small ->
-- | Lens signifying that the @small@ type is
-- a constituent part of the @large@ type
Lens' large small ->
PropertyT m ()
wellFormedLens genLarge genSmall o = do
getPutLensLaw genLarge genSmall o
putGetLensLaw genLarge o
putPutLensLaw genLarge genSmall o
getPutLensLaw ::
Monad m =>
(Show large, Eq large) =>
(Show small, Eq small) =>
Gen large ->
Gen small ->
Lens' large small ->
PropertyT m ()
getPutLensLaw genLarge genSmall o = do
large <- forAll genLarge
small <- forAll genSmall
annotate "The set-get law must hold for a Lens"
view o (set o small large) === small
putGetLensLaw ::
Monad m =>
(Show large, Eq large) =>
(Show small, Eq small) =>
Gen large ->
Lens' large small ->
PropertyT m ()
putGetLensLaw genLarge o = do
large <- forAll genLarge
annotate "The get-set law must hold for a Lens"
set o (view o large) large === large
putPutLensLaw ::
Monad m =>
(Show large, Eq large) =>
(Show small, Eq small) =>
Gen large ->
Gen small ->
Lens' large small ->
PropertyT m ()
putPutLensLaw genLarge genSmall o = do
large <- forAll genLarge
small1 <- forAll genSmall
small2 <- forAll genSmall
annotate "The set-set law must hold for a Lens"
set o small2 (set o small1 large) === set o small2 large
-- | Checks whether an isomorphism respects the
-- well-formedness laws given in "Optics.Iso"
wellFormedIso ::
Monad m =>
(Show a, Eq a) =>
(Show b, Eq b) =>
Gen a ->
Gen b ->
-- | Isomorphism signifying that types
-- @a@ and @b@ are basically the same thing
Iso' a b ->
PropertyT m ()
wellFormedIso genA genB o = do
setGetIsoLaw genB o
getSetIsoLaw genA o
setGetIsoLaw ::
Monad m =>
(Show a, Eq a) =>
(Show b, Eq b) =>
Gen b ->
Iso' a b ->
PropertyT m ()
setGetIsoLaw genB o = do
b <- forAll genB
annotate "The set-get law must hold for an Iso"
(view o . review o) b === b
getSetIsoLaw ::
Monad m =>
(Show a, Eq a) =>
(Show b, Eq b) =>
Gen a ->
Iso' a b ->
PropertyT m ()
getSetIsoLaw genA o = do
a <- forAll genA
annotate "The get-set law must hold for an Iso"
(review o . view o) a === a
-- | Assert that a prism matches for a particular set of values
--
-- A 'review' of the @small@ value should produce the @large@ value, and
-- a 'preview' of the @large@ value should produce the @small@ value.
prismExample ::
Monad m =>
(Show large, Eq large) =>
(Show small, Eq small) =>
-- | Prism signifying that the @small@
-- type is a subset of the @large@ type
Prism' large small ->
large ->
small ->
PropertyT m ()
prismExample o large small = do
review o small === large
preview o large === Just small