{-# LANGUAGE RankNTypes #-}

module Heck where

import qualified Control.Monad as Monad
import qualified GHC.Stack as Stack

data Test m n = MkTest
  { forall (m :: * -> *) (n :: * -> *).
Test m n -> forall x. HasCallStack => String -> m x
assertFailure :: forall x. (Stack.HasCallStack) => String -> m x,
    forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
describe :: String -> n () -> n (),
    forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
it :: String -> m () -> n ()
  }

assertEq :: (Stack.HasCallStack, Applicative m, Eq a, Show a) => Test m n -> a -> a -> m ()
assertEq :: forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
assertEq Test m n
t a
x a
y = Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.unless (a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y) (m () -> m ()) -> (String -> m ()) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Test m n -> forall x. HasCallStack => String -> m x
forall (m :: * -> *) (n :: * -> *).
Test m n -> forall x. HasCallStack => String -> m x
assertFailure Test m n
t (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"expected: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
x String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" == " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
y

assertNe :: (Stack.HasCallStack, Applicative m, Eq a, Show a) => Test m n -> a -> a -> m ()
assertNe :: forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Eq a, Show a) =>
Test m n -> a -> a -> m ()
assertNe Test m n
t a
x a
y = Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.unless (a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
y) (m () -> m ()) -> (String -> m ()) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Test m n -> forall x. HasCallStack => String -> m x
forall (m :: * -> *) (n :: * -> *).
Test m n -> forall x. HasCallStack => String -> m x
assertFailure Test m n
t (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"expected: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
x String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" /= " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
y

assertLt :: (Stack.HasCallStack, Applicative m, Ord a, Show a) => Test m n -> a -> a -> m ()
assertLt :: forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Ord a, Show a) =>
Test m n -> a -> a -> m ()
assertLt Test m n
t a
x a
y = Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.unless (a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
y) (m () -> m ()) -> (String -> m ()) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Test m n -> forall x. HasCallStack => String -> m x
forall (m :: * -> *) (n :: * -> *).
Test m n -> forall x. HasCallStack => String -> m x
assertFailure Test m n
t (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"expected: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
x String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" < " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
y

assertLe :: (Stack.HasCallStack, Applicative m, Ord a, Show a) => Test m n -> a -> a -> m ()
assertLe :: forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Ord a, Show a) =>
Test m n -> a -> a -> m ()
assertLe Test m n
t a
x a
y = Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.unless (a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
y) (m () -> m ()) -> (String -> m ()) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Test m n -> forall x. HasCallStack => String -> m x
forall (m :: * -> *) (n :: * -> *).
Test m n -> forall x. HasCallStack => String -> m x
assertFailure Test m n
t (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"expected: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
x String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" <= " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
y

assertGt :: (Stack.HasCallStack, Applicative m, Ord a, Show a) => Test m n -> a -> a -> m ()
assertGt :: forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Ord a, Show a) =>
Test m n -> a -> a -> m ()
assertGt Test m n
t a
x a
y = Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.unless (a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
> a
y) (m () -> m ()) -> (String -> m ()) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Test m n -> forall x. HasCallStack => String -> m x
forall (m :: * -> *) (n :: * -> *).
Test m n -> forall x. HasCallStack => String -> m x
assertFailure Test m n
t (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"expected: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
x String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" > " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
y

assertGe :: (Stack.HasCallStack, Applicative m, Ord a, Show a) => Test m n -> a -> a -> m ()
assertGe :: forall (m :: * -> *) a (n :: * -> *).
(HasCallStack, Applicative m, Ord a, Show a) =>
Test m n -> a -> a -> m ()
assertGe Test m n
t a
x a
y = Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.unless (a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
y) (m () -> m ()) -> (String -> m ()) -> String -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Test m n -> forall x. HasCallStack => String -> m x
forall (m :: * -> *) (n :: * -> *).
Test m n -> forall x. HasCallStack => String -> m x
assertFailure Test m n
t (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"expected: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
x String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
" >= " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
y