packages feed

tasty-quickcheck-laws-0.0.2: test/Main.hs

module Main where

import Test.Tasty
import Data.Proxy
import System.Environment
import Control.Monad (ap)
import Test.QuickCheck

import Test.Tasty.QuickCheck.Laws



main :: IO ()
main = do
  setEnv "TASTY_NUM_THREADS" "6"
  setEnv "TASTY_QUICKCHECK_TESTS" "1000"
  defaultMain $ testGroup "Laws"
    [ testGroup "Eq Laws"
      [ testEqLaws pU
      , testEqLaws pB
      , testEqLaws pI
      ]
    , testGroup "Monoid Laws"
      [ testMonoidLaws (Proxy :: Proxy [()])
      , testMonoidLaws (Proxy :: Proxy [Bool])
      , testMonoidLaws (Proxy :: Proxy (Maybe [()]))
      ]
    , testGroup "Functor Laws"
      [ testFunctorLaws1 pMb pU pU (const (==))
      , testFunctorLaws1 pEi pU pU (const (==))
      , testFunctorLaws1 pLs pU pU (const (==))
      , testFunctorLaws2 pMb pU pU pB (const (==))
      , testFunctorLaws2 pEi pU pU pB (const (==))
      , testFunctorLaws2 pLs pU pU pB (const (==))
      , testFunctorLaws3 pMb pU pU pB pI (const (==))
      , testFunctorLaws3 pEi pU pU pB pI (const (==))
      , testFunctorLaws3 pLs pU pU pB pI (const (==))
      ]
    , testGroup "Applicative Laws"
      [ testApplicativeLaws1 pMb pU pU (const (==))
      , testApplicativeLaws1 pEi pU pU (const (==))
      , testApplicativeLaws1 pLs pU pU (const (==))
      , testApplicativeLaws2 pMb pU pU pB (const (==))
      , testApplicativeLaws2 pEi pU pU pB (const (==))
      , testApplicativeLaws2 pLs pU pU pB (const (==))
      , testApplicativeLaws3 pMb pU pU pB pI (const (==))
      , testApplicativeLaws3 pEi pU pU pB pI (const (==))
      , testApplicativeLaws3 pLs pU pU pB pI (const (==))
      ]
    , testGroup "Monad Laws"
      [ testMonadLaws1 pMb pU pU (const (==))
      , testMonadLaws1 pEi pU pU (const (==))
      , testMonadLaws1 pLs pU pU (const (==))
      , testMonadLaws2 pMb pU pU pB (const (==))
      , testMonadLaws2 pEi pU pU pB (const (==))
      , testMonadLaws2 pLs pU pU pB (const (==))
      , testMonadLaws3 pMb pU pU pB pI (const (==))
      , testMonadLaws3 pEi pU pU pB pI (const (==))
      , testMonadLaws3 pLs pU pU pB pI (const (==))
      ]
    , testGroup "State Monad Laws"
      [ testStateMonadLaws pSU pU pU pU stateEq get put
      , testStateMonadLaws pSB pB pB pB stateEq get put
      , testStateMonadLaws pSI pI pI pI stateEq get put
      ]
    , testGroup "Reader Monad Laws"
      [ testReaderMonadLaws pRU pU pU pU pU readerEq ask local
      , testReaderMonadLaws pRB pB pB pB pB readerEq ask local
      , testReaderMonadLaws pRI pI pI pI pI readerEq ask local
      ]
    , testGroup "Error Monad Laws"
      [ testErrorMonadLaws pEU pU pU pU pU (const (==)) throw catch
      , testErrorMonadLaws pEB pU pB pU pU (const (==)) throw catch
      , testErrorMonadLaws pEI pU pI pU pU (const (==)) throw catch
      ]
    , testGroup "Writer Monads"
      [ testGroup "Writer Monad Laws"
        [ testWriterMonadLaws pWU pU pU pU pU (const (==)) tell draft
        , testWriterMonadLaws (pWLs pB) pU (pLs' pB) pU pU (const (==)) tell draft
        , testWriterMonadLaws (pWLs pI) pU (pLs' pI) pU pU (const (==)) tell draft
        ]
      , testGroup "Writer Monad Equivalences"
        [ testWriterMonadEquivalences pWU pU pU pU (const (==)) tell draft listen pass
        , testWriterMonadEquivalences (pWLs pB) pU (pLs' pB) pU (const (==)) tell draft listen pass
        , testWriterMonadEquivalences (pWLs pI) pU (pLs' pI) pU (const (==)) tell draft listen pass
        ]
      ]
    , testGroup "Maybe Monads"
      [ testMaybeMonadLaws pMb pU pU eqMaybe Nothing
      , testMaybeMonadLaws pMb pU pB eqMaybe Nothing
      , testMaybeMonadLaws pMb pU pI eqMaybe Nothing
      ]
    ]



pU = Proxy :: Proxy ()
pB = Proxy :: Proxy Bool
pI = Proxy :: Proxy Int

pMb = Proxy :: Proxy Maybe
pEi = Proxy :: Proxy (Either Int)
pLs = Proxy :: Proxy []

pLs' = const Proxy :: Proxy a -> Proxy [a]

pSU = Proxy :: Proxy (State ())
pSB = Proxy :: Proxy (State Bool)
pSI = Proxy :: Proxy (State Int)

pRU = Proxy :: Proxy (Reader ())
pRB = Proxy :: Proxy (Reader Bool)
pRI = Proxy :: Proxy (Reader Int)

pEU = Proxy :: Proxy (Error ())
pEB = Proxy :: Proxy (Error Bool)
pEI = Proxy :: Proxy (Error Int)

pWU = Proxy :: Proxy (Writer ())
pWLs = const Proxy :: Proxy a -> Proxy (Writer [a])



eqMaybe :: (Eq a) => () -> Maybe a -> Maybe a -> Bool
eqMaybe () = (==)

-- Basic State Monad

data State s a = State
  { runState :: s -> (a,s) }

stateEq
  :: (Eq s, Eq a)
  => s -> State s a -> State s a -> Bool
stateEq s x y = (runState x s) == (runState y s)

instance Monad (State s) where
  return a = State $ \s -> (a,s)

  x >>= f = State $ \s1 ->
    let (a,s2) = runState x s1
    in runState (f a) s2

instance Applicative (State s) where
  pure = return
  (<*>) = ap

instance Functor (State s) where
  fmap f x = x >>= (return . f)

instance (Arbitrary a) => Arbitrary (State s a) where
  arbitrary = return <$> arbitrary

get :: State s s
get = State $ \s -> (s,s)

put :: s -> State s ()
put s = State $ \_ -> ((),s)



-- Basic Reader Monad

data Reader r a = Reader
  { runReader :: r -> a }

readerEq
  :: (Eq a)
  => r -> Reader r a -> Reader r a -> Bool
readerEq r x y = (runReader x r) == (runReader y r)

instance Monad (Reader r) where
  return a = Reader $ \_ -> a

  x >>= f = Reader $ \r ->
    let a = runReader x r
    in runReader (f a) r

instance Applicative (Reader r) where
  pure = return
  (<*>) = ap

instance Functor (Reader r) where
  fmap f x = x >>= (return . f)

instance (Arbitrary a, CoArbitrary r) => Arbitrary (Reader r a) where
  arbitrary = Reader <$> arbitrary

instance Show (Reader r a) where
  show _ = "<Reader>"

ask :: Reader r r
ask = Reader $ \r -> r

local :: (r -> r) -> Reader r a -> Reader r a
local u x = Reader $ \r -> runReader x (u r)



-- Basic Error Monad

data Error e a = Error
  { runError :: Either e a
  } deriving (Eq, Show)

instance Monad (Error e) where
  return a = Error (Right a)

  x >>= f = case x of
    Error (Left e) -> Error (Left e)
    Error (Right a) -> f a

instance Applicative (Error e) where
  pure = return
  (<*>) = ap

instance Functor (Error e) where
  fmap f x = x >>= (return . f)

instance (Arbitrary a, Arbitrary e) => Arbitrary (Error e a) where
  arbitrary = Error <$> arbitrary

throw :: e -> Error e a
throw e = Error (Left e)

catch :: Error e a -> (e -> Error e a) -> Error e a
catch x h = case x of
  Error (Right a) -> Error (Right a)
  Error (Left e) -> h e



-- Basic Writer Monad

data Writer w a = Writer
  { runWriter :: (a,w)
  } deriving (Eq, Show)

instance (Monoid w) => Monad (Writer w) where
  return a = Writer (a, mempty)

  x >>= f =
    let
      (a,w1) = runWriter x
      (b,w2) = runWriter (f a)
    in
      Writer (b, mappend w1 w2)

instance (Monoid w) => Applicative (Writer w) where
  pure = return
  (<*>) = ap

instance (Monoid w) => Functor (Writer w) where
  fmap f x = x >>= (return . f)

instance (Arbitrary w, Arbitrary a) => Arbitrary (Writer w a) where
  arbitrary = Writer <$> arbitrary

tell :: w -> Writer w ()
tell w = Writer ((),w)

draft :: (Monoid w) => Writer w a -> Writer w (a,w)
draft x =
  let (a,w) = runWriter x
  in Writer ((a,w), mempty)

listen :: Writer w a -> Writer w (a,w)
listen x =
  let (a,w) = runWriter x
  in Writer ((a,w), w)

pass :: Writer w (a, w -> w) -> Writer w a
pass x =
  let
    ((a,f),w) = runWriter x
  in
    Writer (a, f w)