{-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeOperators #-} module TestEnum where import Control.Arrow import Cybus.Fin import Cybus.FinMat import Cybus.Mat import Cybus.NatHelper import Data.Foldable import Data.List.NonEmpty (NonEmpty (..)) import qualified Data.List.NonEmpty as N import Data.Pos import Primus.AsMaybe import Primus.Enum import Primus.Rep import Test.Tasty import Test.Tasty.HUnit suite :: TestTree suite = testGroup "TestEnum" [ testCase "toEnum" $ toEnum @(Mat2 3 4 ()) 0 @?= mat' @(NS '[3, 4]) (replicate 12 ()) , testCase "toEnum" $ toEnum @(Mat (NS '[2, 3]) ()) 0 @?= mat' @(NS '[2, 3]) [(), (), (), (), (), ()] , testCase "toEnum" $ left (const ()) (toEnumRep @(Mat (NS '[2, 3])) @() 2) @?= Left () , testCase "toenum" $ toEnum @(Fin 10) 0 @?= FinU _1P _10P , testCase "toenum" $ toEnum @(Fin 10) 1 @?= FinU _2P _10P , testCase "toenum" $ toEnum @(Fin 10) 2 @?= FinU _3P _10P , testCase "toenum" $ toEnum @(Fin 2) 1 @?= FinU _2P _2P , testCase "min" $ minBound @(Fin 5) @?= FinU _1P _5P , testCase "max" $ maxBound @(Fin 5) @?= FinU _5P _5P , testCase "toEnumList" $ toEnumList @(FinMat (NS '[3, 4])) (-2) @?= Left "calcNextEnum:not defined for negative numbers" , testCase "toEnumList" $ toEnumList @(FinMat (NS '[3, 4])) (-1) @?= Left "calcNextEnum:not defined for negative numbers" , testCase "toEnumList" $ toEnumList @(FinMat (NS '[3, 4])) 0 @?= Right [] , testCase "toEnumList" $ toEnumList @(FinMat (NS '[3, 4])) 1 @?= Right [FinMatU 1 (_3P :| [_4P])] , testCase "toEnumList" $ toEnumList @(FinMat (NS '[3, 4])) 4 @?= Right [FinMatU 4 (_3P :| [_4P])] , testCase "toEnumList" $ toEnumList @(FinMat (NS '[3, 4])) 5 @?= Right [FinMatU 5 (_3P :| [_4P])] , testCase "toEnumList" $ toEnumList @(FinMat (NS '[1, 1, 1, 1])) (-2) @?= Left "calcNextEnum:not defined for negative numbers" , testCase "toEnumList" $ toEnumList @(FinMat (NS '[1, 1, 1, 1])) 0 @?= Right [] , testCase "toEnumList" $ toEnumList @(FinMat (NS '[1, 1, 1, 1])) 2 @?= Left "calcNextEnum:not defined for positive numbers" , testCase "toEnumList" $ toEnumList @(Fin 1) (-1) @?= Left "calcNextEnum:not defined for negative numbers" , testCase "toEnumList" $ toEnumList @(Fin 1) 0 @?= Right [] , testCase "toEnumList" $ toEnumList @(Fin 1) 1 @?= Left "calcNextEnum:not defined for positive numbers" , testCase "toEnumList" $ toEnumList @(Fin 2) (-10) @?= Left "calcNextEnum:not defined for negative numbers" , testCase "toEnumList" $ toEnumList @(Fin 2) 0 @?= Right [] , testCase "toEnumList" $ toEnumList @(Fin 2) 1 @?= Right [FinU _2P _2P :: Fin 2] , testCase "toEnumList" $ toEnumList @(Fin 2) 12 @?= Right [FinU _2P _2P, FinU _2P _2P, FinU _1P _2P, FinU _1P _2P :: Fin 2] , testCase "toEnumList" $ toEnumList @(Fin 2) 100 @?= Right [FinU _2P _2P, FinU _2P _2P, FinU _1P _2P, FinU _1P _2P, FinU _2P _2P, FinU _1P _2P, FinU _1P _2P :: Fin 2] , testCase "universe1 fin" $ universe1 @(Fin 5) @?= FinU @5 _1P _5P :| [FinU @5 _2P _5P, FinU @5 _3P _5P, FinU @5 _4P _5P, FinU @5 _5P _5P] , testCase "universe1 nextfin" $ iterateT1 succSafe (FinU _1P _5P) @?= FinU @5 _1P _5P :| [FinU @5 _2P _5P, FinU @5 _3P _5P, FinU @5 _4P _5P, FinU @5 _5P _5P] , testCase "universe1 prevfin" $ let f5 = FinU @5 _1P _5P :| [FinU @5 _2P _5P, FinU @5 _3P _5P, FinU @5 _4P _5P, FinU @5 _5P _5P] in iterateT1 predSafe (N.last f5) @?= N.reverse f5 , testCase "universe1 prevfin" $ iterateT1 predSafe (FinU @5 _1P _5P) @?= FinU _1P _5P :| [] , testCase "toEnumRep" $ toEnumRep @(Mat (NS '[4])) @Ordering 10 @?= Right (mat' @(NS '[4]) [LT, EQ, LT, EQ]) , testCase "toEnumRep" $ toEnumRep @(Mat (NS '[4])) @Ordering 0 @?= Right (mat' @(NS '[4]) [LT, LT, LT, LT]) , testCase "toEnumList" $ toEnumList @(Vec 3 Ordering) 0 @?= Right [] , testCase "toEnumList" $ toEnumList @(Vec 3 Ordering) 1 @?= Right [mat' @(NS '[3]) [LT, LT, EQ]] , testCase "toEnumList" $ toEnumList @(Vec 3 Ordering) 200 @?= Right [mat' @(NS '[3]) [LT, GT, EQ], mat' @(NS '[3]) [EQ, LT, GT]] , testCase "toEnumList1" $ toEnumList1 @(Vec 3 Ordering) 0 @?= Right (mat' @(NS '[3]) [LT, LT, LT] :| []) , testCase "toEnumList1" $ toEnumList1 @(Vec 3 Ordering) 1 @?= Right (mat' @(NS '[3]) [LT, LT, EQ] :| []) , testCase "toEnumList1" $ toEnumList1 @(Vec 3 Ordering) 26 @?= Right (mat' @(NS '[3]) [GT, GT, GT] :| []) , testCase "toEnumList1" $ toEnumList1 @(Vec 3 Ordering) 27 @?= Right (mat' @(NS '[3]) [LT, LT, EQ] :| [mat' @(NS '[3]) [LT, LT, LT]]) , testCase "toEnumList1" $ toEnumList1 @(Vec 3 Ordering) 200 @?= Right (mat' @(NS '[3]) [LT, GT, EQ] :| [mat' @(NS '[3]) [EQ, LT, GT]]) , testCase "succTraversable" $ universe1 @(Vec 3 Ordering) @?= iterateT1 succSafe minBound , testCase "toEnumList" $ toEnumList @(Vec 3 ()) 1 @?= Left "calcNextEnum:not defined for positive numbers" , testCase "toEnumList" $ toEnumList @(Vec 3 ()) 0 @?= Right [] , testCase "toEnumList1" $ toEnumList1 @(Vec 3 ()) 0 @?= Right ((() .: () .| ()) :| []) , testCase "toEnumList" $ toEnumList @(Vec 3 Bool) 20 @?= Right [False .: True .| False, True .: False .| False] , testCase "toEnumList1" $ toEnumList1 @(Vec 3 Bool) 20 @?= Right ((False .: True .| False) :| [True .: False .| False]) , testCase "toEnumTraversable" $ toEnumTraversable @Ordering (pure @(Mat (NS '[6])) ()) 10 @?= Right (LT .: LT .: LT .: EQ .: LT .| EQ) , testCase "toEnumRep" $ toEnumRep @(Mat (NS '[6])) @Ordering 10 @?= Right (LT .: LT .: LT .: EQ .: LT .| EQ) , testCase "universe1" $ universe1 @(FinMat (NN 123)) @?= let ns = _1P :| [_2P, _3P] in FinMatU 0 ns :| [FinMatU 1 ns, FinMatU 2 ns, FinMatU 3 ns, FinMatU 4 ns, FinMatU 5 ns] , testCase "universeTraversable" $ universeTraversable (pure @(Vec 2) GT) @?= Right ((LT .| LT) :| [LT .| EQ, LT .| GT, EQ .| LT, EQ .| EQ, EQ .| GT, GT .| LT, GT .| EQ, GT .| GT]) , testCase "universeTraversable" $ universeTraversable (replicate 2 (minBound @(Fin 5))) @?= let ff p n = FinU @5 p n in Right ([ff _1P _5P, ff _1P _5P] :| [[ff _1P _5P, ff _2P _5P], [ff _1P _5P, ff _3P _5P], [ff _1P _5P, ff _4P _5P], [ff _1P _5P, ff _5P _5P], [ff _2P _5P, ff _1P _5P], [ff _2P _5P, ff _2P _5P], [ff _2P _5P, ff _3P _5P], [ff _2P _5P, ff _4P _5P], [ff _2P _5P, ff _5P _5P], [ff _3P _5P, ff _1P _5P], [ff _3P _5P, ff _2P _5P], [ff _3P _5P, ff _3P _5P], [ff _3P _5P, ff _4P _5P], [ff _3P _5P, ff _5P _5P], [ff _4P _5P, ff _1P _5P], [ff _4P _5P, ff _2P _5P], [ff _4P _5P, ff _3P _5P], [ff _4P _5P, ff _4P _5P], [ff _4P _5P, ff _5P _5P], [ff _5P _5P, ff _1P _5P], [ff _5P _5P, ff _2P _5P], [ff _5P _5P, ff _3P _5P], [ff _5P _5P, ff _4P _5P], [ff _5P _5P, ff _5P _5P]]) , testCase "universeTraversable" $ universeTraversable (vec @2 (repeat (finMatC @(1 ':| '[1]) @(2 ':| '[3])))) @?= let ff i = FinMatU i (_2P :| [_3P]) in Right ((ff 0 .| ff 0) :| [ff 0 .| ff 1, ff 0 .| ff 2, ff 0 .| ff 3, ff 0 .| ff 4, ff 0 .| ff 5, ff 1 .| ff 0, ff 1 .| ff 1, ff 1 .| ff 2, ff 1 .| ff 3, ff 1 .| ff 4, ff 1 .| ff 5, ff 2 .| ff 0, ff 2 .| ff 1, ff 2 .| ff 2, ff 2 .| ff 3, ff 2 .| ff 4, ff 2 .| ff 5, ff 3 .| ff 0, ff 3 .| ff 1, ff 3 .| ff 2, ff 3 .| ff 3, ff 3 .| ff 4, ff 3 .| ff 5, ff 4 .| ff 0, ff 4 .| ff 1, ff 4 .| ff 2, ff 4 .| ff 3, ff 4 .| ff 4, ff 4 .| ff 5, ff 5 .| ff 0, ff 5 .| ff 1, ff 5 .| ff 2, ff 5 .| ff 3, ff 5 .| ff 4, ff 5 .| ff 5]) , testCase "capacity" $ capacity @(FinMat (2 ':| '[3])) (replicate 2 ()) @?= Right (0, 35) , testCase "capacity" $ capacity @(FinMat (1 ':| '[3, 5, 6])) (replicate 7 ()) @?= Right (0, 47829689999999) , testCase "iterateT1 succTraversable FinMat" $ fmap (toList . fmap fmPos) (iterateT1 succTraversable (vec' @2 [finMatC @(NS '[3, 3]) @(NS '[4, 3]), finMatC @(NS '[2, 1]) @(NS '[4, 3])])) @?= [8, 3] :| [[8, 4], [8, 5], [8, 6], [8, 7], [8, 8], [8, 9], [8, 10], [8, 11], [9, 0], [9, 1], [9, 2], [9, 3], [9, 4], [9, 5], [9, 6], [9, 7], [9, 8], [9, 9], [9, 10], [9, 11], [10, 0], [10, 1], [10, 2], [10, 3], [10, 4], [10, 5], [10, 6], [10, 7], [10, 8], [10, 9], [10, 10], [10, 11], [11, 0], [11, 1], [11, 2], [11, 3], [11, 4], [11, 5], [11, 6], [11, 7], [11, 8], [11, 9], [11, 10], [11, 11]] , testCase "iterateT1 succTraversable FinMat" $ fmap (toList . fmap fmPos) (iterateT1 succTraversable [finMatC @(NS '[3, 3]) @(NS '[3, 3]), finMatC @(NS '[2, 1]), finMatC @(NS '[3, 1])]) @?= [8, 3, 6] :| [[8, 3, 7], [8, 3, 8], [8, 4, 0], [8, 4, 1], [8, 4, 2], [8, 4, 3], [8, 4, 4], [8, 4, 5], [8, 4, 6], [8, 4, 7], [8, 4, 8], [8, 5, 0], [8, 5, 1], [8, 5, 2], [8, 5, 3], [8, 5, 4], [8, 5, 5], [8, 5, 6], [8, 5, 7], [8, 5, 8], [8, 6, 0], [8, 6, 1], [8, 6, 2], [8, 6, 3], [8, 6, 4], [8, 6, 5], [8, 6, 6], [8, 6, 7], [8, 6, 8], [8, 7, 0], [8, 7, 1], [8, 7, 2], [8, 7, 3], [8, 7, 4], [8, 7, 5], [8, 7, 6], [8, 7, 7], [8, 7, 8], [8, 8, 0], [8, 8, 1], [8, 8, 2], [8, 8, 3], [8, 8, 4], [8, 8, 5], [8, 8, 6], [8, 8, 7], [8, 8, 8]] , testCase "iterateT1 succTraversable Fin" $ fmap (toList . fmap fnPos) (iterateT1 succTraversable [finC @4 @5, finC @3, finC @2]) @?= [_4P, _3P, _2P] :| [[_4P, _3P, _3P], [_4P, _3P, _4P], [_4P, _3P, _5P], [_4P, _4P, _1P], [_4P, _4P, _2P], [_4P, _4P, _3P], [_4P, _4P, _4P], [_4P, _4P, _5P], [_4P, _5P, _1P], [_4P, _5P, _2P], [_4P, _5P, _3P], [_4P, _5P, _4P], [_4P, _5P, _5P], [_5P, _1P, _1P], [_5P, _1P, _2P], [_5P, _1P, _3P], [_5P, _1P, _4P], [_5P, _1P, _5P], [_5P, _2P, _1P], [_5P, _2P, _2P], [_5P, _2P, _3P], [_5P, _2P, _4P], [_5P, _2P, _5P], [_5P, _3P, _1P], [_5P, _3P, _2P], [_5P, _3P, _3P], [_5P, _3P, _4P], [_5P, _3P, _5P], [_5P, _4P, _1P], [_5P, _4P, _2P], [_5P, _4P, _3P], [_5P, _4P, _4P], [_5P, _4P, _5P], [_5P, _5P, _1P], [_5P, _5P, _2P], [_5P, _5P, _3P], [_5P, _5P, _4P], [_5P, _5P, _5P]] , testCase "iterateT1 predTraversable Fin" $ fmap (toList . fmap fnPos) (iterateT1 predTraversable [finC @4 @5, finC @3, finC @2]) @?= [_4P, _3P, _2P] :| [[_4P, _3P, _1P], [_4P, _2P, _5P], [_4P, _2P, _4P], [_4P, _2P, _3P], [_4P, _2P, _2P], [_4P, _2P, _1P], [_4P, _1P, _5P], [_4P, _1P, _4P], [_4P, _1P, _3P], [_4P, _1P, _2P], [_4P, _1P, _1P], [_3P, _5P, _5P], [_3P, _5P, _4P], [_3P, _5P, _3P], [_3P, _5P, _2P], [_3P, _5P, _1P], [_3P, _4P, _5P], [_3P, _4P, _4P], [_3P, _4P, _3P], [_3P, _4P, _2P], [_3P, _4P, _1P], [_3P, _3P, _5P], [_3P, _3P, _4P], [_3P, _3P, _3P], [_3P, _3P, _2P], [_3P, _3P, _1P], [_3P, _2P, _5P], [_3P, _2P, _4P], [_3P, _2P, _3P], [_3P, _2P, _2P], [_3P, _2P, _1P], [_3P, _1P, _5P], [_3P, _1P, _4P], [_3P, _1P, _3P], [_3P, _1P, _2P], [_3P, _1P, _1P], [_2P, _5P, _5P], [_2P, _5P, _4P], [_2P, _5P, _3P], [_2P, _5P, _2P], [_2P, _5P, _1P], [_2P, _4P, _5P], [_2P, _4P, _4P], [_2P, _4P, _3P], [_2P, _4P, _2P], [_2P, _4P, _1P], [_2P, _3P, _5P], [_2P, _3P, _4P], [_2P, _3P, _3P], [_2P, _3P, _2P], [_2P, _3P, _1P], [_2P, _2P, _5P], [_2P, _2P, _4P], [_2P, _2P, _3P], [_2P, _2P, _2P], [_2P, _2P, _1P], [_2P, _1P, _5P], [_2P, _1P, _4P], [_2P, _1P, _3P], [_2P, _1P, _2P], [_2P, _1P, _1P], [_1P, _5P, _5P], [_1P, _5P, _4P], [_1P, _5P, _3P], [_1P, _5P, _2P], [_1P, _5P, _1P], [_1P, _4P, _5P], [_1P, _4P, _4P], [_1P, _4P, _3P], [_1P, _4P, _2P], [_1P, _4P, _1P], [_1P, _3P, _5P], [_1P, _3P, _4P], [_1P, _3P, _3P], [_1P, _3P, _2P], [_1P, _3P, _1P], [_1P, _2P, _5P], [_1P, _2P, _4P], [_1P, _2P, _3P], [_1P, _2P, _2P], [_1P, _2P, _1P], [_1P, _1P, _5P], [_1P, _1P, _4P], [_1P, _1P, _3P], [_1P, _1P, _2P], [_1P, _1P, _1P]] ]