{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}

-- | Dummy types used in tests
module Plutarch.Test.SpecTypes (Triplet (..), PTriplet (..)) where

import Data.Kind (Type)
import GHC.Generics (Generic)
import Plutarch.Prelude
import PlutusTx qualified
import Prettyprinter (Pretty (pretty), (<+>))
import Test.Tasty.QuickCheck (Arbitrary, arbitrary)

{- | Tuple of three elements of the same type

@since WIP
-}
data Triplet a = Triplet a a a
  deriving stock (Int -> Triplet a -> ShowS
[Triplet a] -> ShowS
Triplet a -> String
(Int -> Triplet a -> ShowS)
-> (Triplet a -> String)
-> ([Triplet a] -> ShowS)
-> Show (Triplet a)
forall a. Show a => Int -> Triplet a -> ShowS
forall a. Show a => [Triplet a] -> ShowS
forall a. Show a => Triplet a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Triplet a -> ShowS
showsPrec :: Int -> Triplet a -> ShowS
$cshow :: forall a. Show a => Triplet a -> String
show :: Triplet a -> String
$cshowList :: forall a. Show a => [Triplet a] -> ShowS
showList :: [Triplet a] -> ShowS
Show, Triplet a -> Triplet a -> Bool
(Triplet a -> Triplet a -> Bool)
-> (Triplet a -> Triplet a -> Bool) -> Eq (Triplet a)
forall a. Eq a => Triplet a -> Triplet a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Triplet a -> Triplet a -> Bool
== :: Triplet a -> Triplet a -> Bool
$c/= :: forall a. Eq a => Triplet a -> Triplet a -> Bool
/= :: Triplet a -> Triplet a -> Bool
Eq, Eq (Triplet a)
Eq (Triplet a) =>
(Triplet a -> Triplet a -> Ordering)
-> (Triplet a -> Triplet a -> Bool)
-> (Triplet a -> Triplet a -> Bool)
-> (Triplet a -> Triplet a -> Bool)
-> (Triplet a -> Triplet a -> Bool)
-> (Triplet a -> Triplet a -> Triplet a)
-> (Triplet a -> Triplet a -> Triplet a)
-> Ord (Triplet a)
Triplet a -> Triplet a -> Bool
Triplet a -> Triplet a -> Ordering
Triplet a -> Triplet a -> Triplet a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Triplet a)
forall a. Ord a => Triplet a -> Triplet a -> Bool
forall a. Ord a => Triplet a -> Triplet a -> Ordering
forall a. Ord a => Triplet a -> Triplet a -> Triplet a
$ccompare :: forall a. Ord a => Triplet a -> Triplet a -> Ordering
compare :: Triplet a -> Triplet a -> Ordering
$c< :: forall a. Ord a => Triplet a -> Triplet a -> Bool
< :: Triplet a -> Triplet a -> Bool
$c<= :: forall a. Ord a => Triplet a -> Triplet a -> Bool
<= :: Triplet a -> Triplet a -> Bool
$c> :: forall a. Ord a => Triplet a -> Triplet a -> Bool
> :: Triplet a -> Triplet a -> Bool
$c>= :: forall a. Ord a => Triplet a -> Triplet a -> Bool
>= :: Triplet a -> Triplet a -> Bool
$cmax :: forall a. Ord a => Triplet a -> Triplet a -> Triplet a
max :: Triplet a -> Triplet a -> Triplet a
$cmin :: forall a. Ord a => Triplet a -> Triplet a -> Triplet a
min :: Triplet a -> Triplet a -> Triplet a
Ord)

instance Pretty a => Pretty (Triplet a) where
  pretty :: forall ann. Triplet a -> Doc ann
pretty (Triplet a
x a
y a
z) = a -> Doc ann
forall ann. a -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty a
x Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> a -> Doc ann
forall ann. a -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty a
y Doc ann -> Doc ann -> Doc ann
forall ann. Doc ann -> Doc ann -> Doc ann
<+> a -> Doc ann
forall ann. a -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty a
z

{- |
  We can defined a data-type using PDataRecord, with labeled fields.

  With an appropriate instance of 'PIsDataRepr', we can automatically
  derive 'PDataFields'.

@since WIP
-}
newtype PTriplet (a :: S -> Type) (s :: S)
  = PTriplet
      ( Term
          s
          ( PDataRecord
              '[ "x" ':= a
               , "y" ':= a
               , "z" ':= a
               ]
          )
      )
  deriving stock ((forall x. PTriplet a s -> Rep (PTriplet a s) x)
-> (forall x. Rep (PTriplet a s) x -> PTriplet a s)
-> Generic (PTriplet a s)
forall x. Rep (PTriplet a s) x -> PTriplet a s
forall x. PTriplet a s -> Rep (PTriplet a s) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (a :: S -> Type) (s :: S) x.
Rep (PTriplet a s) x -> PTriplet a s
forall (a :: S -> Type) (s :: S) x.
PTriplet a s -> Rep (PTriplet a s) x
$cfrom :: forall (a :: S -> Type) (s :: S) x.
PTriplet a s -> Rep (PTriplet a s) x
from :: forall x. PTriplet a s -> Rep (PTriplet a s) x
$cto :: forall (a :: S -> Type) (s :: S) x.
Rep (PTriplet a s) x -> PTriplet a s
to :: forall x. Rep (PTriplet a s) x -> PTriplet a s
Generic)
  deriving anyclass ((forall (s :: S). PTriplet a s -> Term s (PInner (PTriplet a)))
-> (forall (s :: S) (b :: S -> Type).
    Term s (PInner (PTriplet a))
    -> (PTriplet a s -> Term s b) -> Term s b)
-> PlutusType (PTriplet a)
forall (s :: S). PTriplet a s -> Term s (PInner (PTriplet a))
forall (s :: S) (b :: S -> Type).
Term s (PInner (PTriplet a))
-> (PTriplet a s -> Term s b) -> Term s b
forall (a :: S -> Type).
(forall (s :: S). a s -> Term s (PInner a))
-> (forall (s :: S) (b :: S -> Type).
    Term s (PInner a) -> (a s -> Term s b) -> Term s b)
-> PlutusType a
forall (a :: S -> Type) (s :: S).
PTriplet a s -> Term s (PInner (PTriplet a))
forall (a :: S -> Type) (s :: S) (b :: S -> Type).
Term s (PInner (PTriplet a))
-> (PTriplet a s -> Term s b) -> Term s b
$cpcon' :: forall (a :: S -> Type) (s :: S).
PTriplet a s -> Term s (PInner (PTriplet a))
pcon' :: forall (s :: S). PTriplet a s -> Term s (PInner (PTriplet a))
$cpmatch' :: forall (a :: S -> Type) (s :: S) (b :: S -> Type).
Term s (PInner (PTriplet a))
-> (PTriplet a s -> Term s b) -> Term s b
pmatch' :: forall (s :: S) (b :: S -> Type).
Term s (PInner (PTriplet a))
-> (PTriplet a s -> Term s b) -> Term s b
PlutusType, (forall (s :: S).
 Term s (PAsData (PTriplet a)) -> Term s (PTriplet a))
-> (forall (s :: S). Term s (PTriplet a) -> Term s PData)
-> PIsData (PTriplet a)
forall (s :: S).
Term s (PAsData (PTriplet a)) -> Term s (PTriplet a)
forall (s :: S). Term s (PTriplet a) -> Term s PData
forall (a :: S -> Type).
(forall (s :: S). Term s (PAsData a) -> Term s a)
-> (forall (s :: S). Term s a -> Term s PData) -> PIsData a
forall (a :: S -> Type) (s :: S).
Term s (PAsData (PTriplet a)) -> Term s (PTriplet a)
forall (a :: S -> Type) (s :: S).
Term s (PTriplet a) -> Term s PData
$cpfromDataImpl :: forall (a :: S -> Type) (s :: S).
Term s (PAsData (PTriplet a)) -> Term s (PTriplet a)
pfromDataImpl :: forall (s :: S).
Term s (PAsData (PTriplet a)) -> Term s (PTriplet a)
$cpdataImpl :: forall (a :: S -> Type) (s :: S).
Term s (PTriplet a) -> Term s PData
pdataImpl :: forall (s :: S). Term s (PTriplet a) -> Term s PData
PIsData, (forall (s :: S).
 Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool)
-> PEq (PTriplet a)
forall (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
forall (t :: S -> Type).
(forall (s :: S). Term s t -> Term s t -> Term s PBool) -> PEq t
forall (a :: S -> Type) (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
$c#== :: forall (a :: S -> Type) (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
#== :: forall (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
PEq, PEq (PTriplet a)
PEq (PTriplet a) =>
(forall (s :: S).
 Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool)
-> (forall (s :: S).
    Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool)
-> (forall (s :: S).
    Term s (PTriplet a) -> Term s (PTriplet a) -> Term s (PTriplet a))
-> (forall (s :: S).
    Term s (PTriplet a) -> Term s (PTriplet a) -> Term s (PTriplet a))
-> POrd (PTriplet a)
forall (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
forall (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s (PTriplet a)
forall (t :: S -> Type).
PEq t =>
(forall (s :: S). Term s t -> Term s t -> Term s PBool)
-> (forall (s :: S). Term s t -> Term s t -> Term s PBool)
-> (forall (s :: S). Term s t -> Term s t -> Term s t)
-> (forall (s :: S). Term s t -> Term s t -> Term s t)
-> POrd t
forall (a :: S -> Type). (POrd a, PIsData a) => PEq (PTriplet a)
forall (a :: S -> Type) (s :: S).
(POrd a, PIsData a) =>
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
forall (a :: S -> Type) (s :: S).
(POrd a, PIsData a) =>
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s (PTriplet a)
$c#<= :: forall (a :: S -> Type) (s :: S).
(POrd a, PIsData a) =>
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
#<= :: forall (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
$c#< :: forall (a :: S -> Type) (s :: S).
(POrd a, PIsData a) =>
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
#< :: forall (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s PBool
$cpmax :: forall (a :: S -> Type) (s :: S).
(POrd a, PIsData a) =>
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s (PTriplet a)
pmax :: forall (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s (PTriplet a)
$cpmin :: forall (a :: S -> Type) (s :: S).
(POrd a, PIsData a) =>
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s (PTriplet a)
pmin :: forall (s :: S).
Term s (PTriplet a) -> Term s (PTriplet a) -> Term s (PTriplet a)
POrd, (forall (s :: S).
 Term s (PTriplet a) -> Term s (PDataRecord (PFields (PTriplet a))))
-> PDataFields (PTriplet a)
forall (s :: S).
Term s (PTriplet a) -> Term s (PDataRecord (PFields (PTriplet a)))
forall (a :: S -> Type).
(forall (s :: S). Term s a -> Term s (PDataRecord (PFields a)))
-> PDataFields a
forall (a :: S -> Type) (s :: S).
Term s (PTriplet a) -> Term s (PDataRecord (PFields (PTriplet a)))
$cptoFields :: forall (a :: S -> Type) (s :: S).
Term s (PTriplet a) -> Term s (PDataRecord (PFields (PTriplet a)))
ptoFields :: forall (s :: S).
Term s (PTriplet a) -> Term s (PDataRecord (PFields (PTriplet a)))
PDataFields)

-- | @since WIP
instance DerivePlutusType (PTriplet a) where type DPTStrat _ = PlutusTypeData

PlutusTx.makeIsDataIndexed ''Triplet [('Triplet, 0)]

-- | @since WIP
instance Arbitrary a => Arbitrary (Triplet a) where
  arbitrary :: Gen (Triplet a)
arbitrary = a -> a -> a -> Triplet a
forall a. a -> a -> a -> Triplet a
Triplet (a -> a -> a -> Triplet a) -> Gen a -> Gen (a -> a -> Triplet a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen a
forall a. Arbitrary a => Gen a
arbitrary Gen (a -> a -> Triplet a) -> Gen a -> Gen (a -> Triplet a)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> Gen a
forall a. Arbitrary a => Gen a
arbitrary Gen (a -> Triplet a) -> Gen a -> Gen (Triplet a)
forall a b. Gen (a -> b) -> Gen a -> Gen b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> Gen a
forall a. Arbitrary a => Gen a
arbitrary

-- | @since WIP
deriving via
  DeriveDataPLiftable (PTriplet a) (Triplet (AsHaskell a))
  instance
    (PlutusTx.ToData (AsHaskell a), PlutusTx.FromData (AsHaskell a)) => PLiftable (PTriplet a)