-- Copyright (c) 2019-2025 Rudy Matela. -- Distributed under the 3-Clause BSD licence (see the file LICENSE). {-# LANGUAGE TemplateHaskell #-} -- uncomment to debug derivation: -- {-# OPTIONS_GHC -ddump-splices #-} import Test hiding ((-:), (->:)) -- -: and ->: should be generated by deriveConjurable -- replication of Haskell's built-in data types -- in the order of the Haskell98 standard -- https://www.haskell.org/onlinereport/basic.html data Choice = Yes | No deriving (Show, Eq) data Peano = Zero | Succ Peano deriving (Show, Eq) data Lst a = Nil | a :- Lst a deriving (Show, Eq) data Unit = Unit deriving (Show, Eq) data Perhaps a = Naught | Precisely a deriving (Show, Eq) data Alternatively a b = Sinister a | Dexter b deriving (Show, Eq) data Relation = Smaller | Same | Bigger deriving (Show, Eq) deriveConjurable ''Choice deriveConjurable ''Peano deriveConjurable ''Lst deriveConjurable ''Unit deriveConjurable ''Perhaps deriveConjurable ''Alternatively deriveConjurable ''Relation -- tree types data Bush a = Bush a :-: Bush a | Leaf a deriving (Show, Eq) data Tree a = Node (Tree a) a (Tree a) | Null deriving (Show, Eq) deriveConjurable ''Bush deriveConjurable ''Tree -- inner/outer data Inner = I deriving (Eq, Ord, Show) data Outer = O Inner deriving (Eq, Ord, Show) deriveConjurableCascading ''Outer -- Nested datatype cascade data Nested = Nested N0 (N1 Int) (N2 Int Int) deriving (Eq, Show) data N0 = R0 Int deriving (Eq, Show) data N1 a = R1 a deriving (Eq, Show) data N2 a b = R2 a b deriving (Eq, Show) deriveConjurableCascading ''Nested -- Recursive nested datatype cascade data RN = RN RN0 (RN1 Int) (RN2 Int RN0) deriving (Eq, Show) data RN0 = Nest0 Int | Recurse0 RN deriving (Eq, Show) data RN1 a = Nest1 a | Recurse1 RN deriving (Eq, Show) data RN2 a b = Nest2 a b | Recurse2 RN deriving (Eq, Show) deriveConjurableCascading ''RN -- Those should have no effect (instance already exists): {- uncommenting those should generate warnings deriveConjurable ''Bool deriveConjurable ''Maybe deriveConjurable ''Either -} -- Those should not generate warnings deriveConjurableIfNeeded ''Bool deriveConjurableIfNeeded ''Maybe deriveConjurableIfNeeded ''Either data Mutual = Mutual0 | Mutual CoMutual deriving (Eq, Show) data CoMutual = CoMutual0 | CoMutual Mutual deriving (Eq, Show) deriveConjurableCascading ''Mutual main :: IO () main = mainTest tests 5040 tests :: Int -> [Bool] tests n = [ True -- re-test standard types , conjurableOK (undefined :: Bool) , conjurableOK (undefined :: Int) , conjurableOK (undefined :: [A]) , conjurableOK (undefined :: [Int]) , conjurableOK (undefined :: [Bool]) , conjurableOK (undefined :: ()) , conjurableOK (undefined :: Maybe A) , conjurableOK (undefined :: Either A B) , conjurableOK (undefined :: Ordering) -- replication of Haskell's built-in types , conjurableOK (undefined :: Choice) , conjurableOK (undefined :: Peano) , conjurableOK (undefined :: Lst A) , conjurableOK (undefined :: Lst Peano) , conjurableOK (undefined :: Lst Choice) , conjurableOK (undefined :: Unit) , conjurableOK (undefined :: Perhaps A) , conjurableOK (undefined :: Alternatively A B) , conjurableOK (undefined :: Relation) -- tree types , conjurableOK (undefined :: Bush Int) , conjurableOK (undefined :: Tree Int) , conjurableOK (undefined :: Inner) , conjurableOK (undefined :: Outer) , conjurableOK (undefined :: RN) , conjurableOK (undefined :: Mutual) , conjurableOK (undefined :: CoMutual) , conjureSize Yes == 1 , conjureSize No == 1 , conjureSize Zero == 1 , conjureSize (Succ Zero) == 2 , conjureSize (Succ (Succ Zero)) == 3 , conjureSize (Succ (Succ (Succ Zero))) == 4 , conjureSize (Nil :: Lst Int) == 1 , conjureSize (10 :- (20 :- Nil) :: Lst Int) == 33 , conjureSize Unit == 1 , conjureCases choice == [ val Yes , val No ] , conjureCases peano == [ val Zero , value "Succ" Succ :$ hole (undefined :: Peano) ] , conjureCases (lst int) == [ val (Nil :: Lst Int) , value ":-" ((:-) ->>: lst int) :$ hole int :$ hole (lst int) ] , conjureCases relation == [ val Smaller , val Same , val Bigger ] , conjureCases (bush int) == [ value ":-:" ((:-:) ->>: bush int) :$ hole (bush int) :$ hole (bush int) , value "Leaf" (Leaf ->: bush int) :$ hole int ] , conjureCases (tree int) == [ value "Node" (Node ->>>: tree int) :$ hole (tree int) :$ hole int :$ hole (tree int) , val (Null :: Tree Int) ] , conjureCases nested == [ value "Nested" Nested :$ hole n0 :$ hole (n1 int) :$ hole (n2 int int) ] , conjureHoles (undefined :: Choice) == [ hole (undefined :: Choice) , hole (undefined :: Bool) ] , conjureHoles (undefined :: Peano) == [ hole (undefined :: Peano) , hole (undefined :: Bool) ] , conjureHoles (undefined :: Lst Int) == [ hole (undefined :: Int) , hole (undefined :: Lst Int) , hole (undefined :: Bool) ] , conjureHoles (undefined :: Lst Peano) == [ hole (undefined :: Peano) , hole (undefined :: Lst Peano) , hole (undefined :: Bool) ] , conjureHoles (undefined :: Nested) == [ hole (undefined :: N0) , hole (undefined :: N1 Int) , hole (undefined :: Int) , hole (undefined :: N2 Int Int) , hole (undefined :: Nested) , hole (undefined :: Bool) ] , conjureHoles (undefined :: RN) == [ hole (undefined :: RN1 Int) , hole (undefined :: Int) , hole (undefined :: RN0) , hole (undefined :: RN2 Int RN0) , hole (undefined :: RN) , hole (undefined :: Bool) ] , conjureHoles (undefined :: Mutual) == [ hole (undefined :: CoMutual) , hole (undefined :: Mutual) , hole (undefined :: Bool) ] , conjureHoles (undefined :: CoMutual) == [ hole (undefined :: Mutual) , hole (undefined :: CoMutual) , hole (undefined :: Bool) ] ] -- proxies -- choice :: Choice choice = undefined peano :: Peano peano = undefined lst :: a -> Lst a lst _ = undefined relation :: Relation relation = undefined bush :: a -> Bush a bush _ = undefined tree :: a -> Tree a tree _ = undefined nested :: Nested nested = undefined n0 :: N0 n0 = undefined n1 :: a -> N1 a n1 _ = undefined n2 :: a -> b -> N2 a b n2 _ _ = undefined