module Hedgehog.Classes.Common.Func
  ( func1
  , func2
  , func3
  , func4
  , func5
  , func6

  , Triple(..), reverseTriple, genTriple
  ) where

import Hedgehog
import Data.Functor.Classes (Eq1(..), Show1(..))
import Data.Functor.Compose
import qualified Data.Set as S
import qualified Control.Monad.Trans.Writer.Lazy as WL
import Data.Semigroup

func1 :: Integer -> (Integer, Integer)
func1 :: Integer -> (Integer, Integer)
func1 Integer
i = (Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
div (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
5) Integer
3, Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
2 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1)

func2 :: (Integer, Integer) -> (Bool, Either Ordering Integer)
func2 :: (Integer, Integer) -> (Bool, Either Ordering Integer)
func2 (Integer
a,Integer
b) = (Integer -> Bool
forall a. Integral a => a -> Bool
odd Integer
a, if Integer -> Bool
forall a. Integral a => a -> Bool
even Integer
a then Ordering -> Either Ordering Integer
forall a b. a -> Either a b
Left (Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
a Integer
b) else Integer -> Either Ordering Integer
forall a b. b -> Either a b
Right (Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
2))

func3 :: Integer -> Sum Integer
func3 :: Integer -> Sum Integer
func3 Integer
i = Integer -> Sum Integer
forall a. a -> Sum a
Sum (Integer
3 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
7 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
4)

func4 :: Integer -> Compose Triple (WL.Writer (S.Set Integer)) Integer
func4 :: Integer -> Compose Triple (Writer (Set Integer)) Integer
func4 Integer
i = Triple (WriterT (Set Integer) Identity Integer)
-> Compose Triple (Writer (Set Integer)) Integer
forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (Triple (WriterT (Set Integer) Identity Integer)
 -> Compose Triple (Writer (Set Integer)) Integer)
-> Triple (WriterT (Set Integer) Identity Integer)
-> Compose Triple (Writer (Set Integer)) Integer
forall a b. (a -> b) -> a -> b
$ WriterT (Set Integer) Identity Integer
-> WriterT (Set Integer) Identity Integer
-> WriterT (Set Integer) Identity Integer
-> Triple (WriterT (Set Integer) Identity Integer)
forall a. a -> a -> a -> Triple a
Triple
  ((Integer, Set Integer) -> WriterT (Set Integer) Identity Integer
forall (m :: * -> *) a w. Monad m => (a, w) -> WriterT w m a
WL.writer (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i, Integer -> Set Integer
forall a. a -> Set a
S.singleton (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
7 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
5)))
  ((Integer, Set Integer) -> WriterT (Set Integer) Identity Integer
forall (m :: * -> *) a w. Monad m => (a, w) -> WriterT w m a
WL.writer (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
2, Integer -> Set Integer
forall a. a -> Set a
S.singleton (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
3)))
  ((Integer, Set Integer) -> WriterT (Set Integer) Identity Integer
forall (m :: * -> *) a w. Monad m => (a, w) -> WriterT w m a
WL.writer (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
7, Integer -> Set Integer
forall a. a -> Set a
S.singleton Integer
4))

func5 :: Integer -> Triple Integer
func5 :: Integer -> Triple Integer
func5 Integer
i = Integer -> Integer -> Integer -> Triple Integer
forall a. a -> a -> a -> Triple a
Triple (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
2) (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
3) (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i)

func6 :: Integer -> Triple Integer
func6 :: Integer -> Triple Integer
func6 Integer
i = Integer -> Integer -> Integer -> Triple Integer
forall a. a -> a -> a -> Triple a
Triple (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i) (Integer
4 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
7) (Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
i)

reverseTriple :: Triple a -> Triple a
reverseTriple :: Triple a -> Triple a
reverseTriple (Triple a
a a
b a
c) = a -> a -> a -> Triple a
forall a. a -> a -> a -> Triple a
Triple a
c a
b a
a

data Triple a = Triple a a a
  deriving (Int -> Triple a -> ShowS
[Triple a] -> ShowS
Triple a -> String
(Int -> Triple a -> ShowS)
-> (Triple a -> String) -> ([Triple a] -> ShowS) -> Show (Triple a)
forall a. Show a => Int -> Triple a -> ShowS
forall a. Show a => [Triple a] -> ShowS
forall a. Show a => Triple a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Triple a] -> ShowS
$cshowList :: forall a. Show a => [Triple a] -> ShowS
show :: Triple a -> String
$cshow :: forall a. Show a => Triple a -> String
showsPrec :: Int -> Triple a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Triple a -> ShowS
Show, Triple a -> Triple a -> Bool
(Triple a -> Triple a -> Bool)
-> (Triple a -> Triple a -> Bool) -> Eq (Triple a)
forall a. Eq a => Triple a -> Triple a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Triple a -> Triple a -> Bool
$c/= :: forall a. Eq a => Triple a -> Triple a -> Bool
== :: Triple a -> Triple a -> Bool
$c== :: forall a. Eq a => Triple a -> Triple a -> Bool
Eq)

instance Functor Triple where
  fmap :: (a -> b) -> Triple a -> Triple b
fmap a -> b
f (Triple a
a a
b a
c) = b -> b -> b -> Triple b
forall a. a -> a -> a -> Triple a
Triple (a -> b
f a
a) (a -> b
f a
b) (a -> b
f a
c)

instance Applicative Triple where
  pure :: a -> Triple a
pure a
a = a -> a -> a -> Triple a
forall a. a -> a -> a -> Triple a
Triple a
a a
a a
a
  Triple a -> b
f a -> b
g a -> b
h <*> :: Triple (a -> b) -> Triple a -> Triple b
<*> Triple a
a a
b a
c = b -> b -> b -> Triple b
forall a. a -> a -> a -> Triple a
Triple (a -> b
f a
a) (a -> b
g a
b) (a -> b
h a
c)

instance Foldable Triple where
  foldMap :: (a -> m) -> Triple a -> m
foldMap a -> m
f (Triple a
a a
b a
c) = a -> m
f a
a m -> m -> m
forall a. Semigroup a => a -> a -> a
<> a -> m
f a
b m -> m -> m
forall a. Semigroup a => a -> a -> a
<> a -> m
f a
c

instance Traversable Triple where
  traverse :: (a -> f b) -> Triple a -> f (Triple b)
traverse a -> f b
f (Triple a
a a
b a
c) = b -> b -> b -> Triple b
forall a. a -> a -> a -> Triple a
Triple (b -> b -> b -> Triple b) -> f b -> f (b -> b -> Triple b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
a f (b -> b -> Triple b) -> f b -> f (b -> Triple b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> a -> f b
f a
b f (b -> Triple b) -> f b -> f (Triple b)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> a -> f b
f a
c

tripleLiftEq :: (a -> b -> Bool) -> Triple a -> Triple b -> Bool
tripleLiftEq :: (a -> b -> Bool) -> Triple a -> Triple b -> Bool
tripleLiftEq a -> b -> Bool
p (Triple a
a1 a
b1 a
c1) (Triple b
a2 b
b2 b
c2) =
  a -> b -> Bool
p a
a1 b
a2 Bool -> Bool -> Bool
&& a -> b -> Bool
p a
b1 b
b2 Bool -> Bool -> Bool
&& a -> b -> Bool
p a
c1 b
c2

tripleLiftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Triple a -> ShowS
tripleLiftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Triple a -> ShowS
tripleLiftShowsPrec Int -> a -> ShowS
elemShowsPrec [a] -> ShowS
_ Int
p (Triple a
a a
b a
c) = Bool -> ShowS -> ShowS
showParen (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10)
  (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$ String -> ShowS
showString String
"Triple "
  ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a -> ShowS
elemShowsPrec Int
11 a
a
  ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" "
  ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a -> ShowS
elemShowsPrec Int
11 a
b
  ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
showString String
" "
  ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a -> ShowS
elemShowsPrec Int
11 a
c

instance Eq1 Triple where
  liftEq :: (a -> b -> Bool) -> Triple a -> Triple b -> Bool
liftEq = (a -> b -> Bool) -> Triple a -> Triple b -> Bool
forall a b. (a -> b -> Bool) -> Triple a -> Triple b -> Bool
tripleLiftEq

instance Show1 Triple where
  liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Triple a -> ShowS
liftShowsPrec = (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Triple a -> ShowS
forall a.
(Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Triple a -> ShowS
tripleLiftShowsPrec

genTriple :: Gen a -> Gen (Triple a)
genTriple :: Gen a -> Gen (Triple a)
genTriple Gen a
gen = a -> a -> a -> Triple a
forall a. a -> a -> a -> Triple a
Triple (a -> a -> a -> Triple a)
-> Gen a -> GenT Identity (a -> a -> Triple a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
gen GenT Identity (a -> a -> Triple a)
-> Gen a -> GenT Identity (a -> Triple a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
gen GenT Identity (a -> Triple a) -> Gen a -> Gen (Triple a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen a
gen