primus-0.1.0.0: test/TestEnum.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module TestEnum where
import Control.Arrow
import Control.Monad
import Data.Int
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as N
import Data.Pos
import Primus.AsMaybe
import Primus.Enum
import Primus.NonEmpty
import Test.Tasty
import Test.Tasty.HUnit
suite :: TestTree
suite =
testGroup
"TestEnum"
[ testCase "enumFrom1" $ take1 _5P (enumFrom1 _5P) @?= (_5P :| [_6P, _7P, _8P, _9P])
, testCase "enumFrom1R" $ enumFrom1R _5P @?= (_5P :| [_4P, _3P, _2P, _1P])
, testCase "enumFrom1R" $ enumFrom1R _1P @?= (_1P :| [])
, testCase "enumTo1" $ enumTo1 _5P @?= (_1P :| [_2P, _3P, _4P, _5P])
, testCase "enumTo1" $ enumTo1 _1P @?= (_1P :| [])
, testCase "enumTo1" $ enumTo1 EQ @?= (LT :| [EQ])
, testCase "enumTo1" $ enumTo1 LT @?= (LT :| [])
, testCase "enumTo1" $ enumTo1 GT @?= (LT :| [EQ, GT])
, testCase "enumFromThen1" $ take1 _5P (enumFromThen1 _5P _11P) @?= (_5P :| [_11P, _17P, _P @23, _P @29])
, testCase "enumFromThen1" $ enumFromThen1 _15P _10P @?= (_15P :| [_10P, _5P])
, testCase "enumFromThen1" $ enumFromThen1 _5P _5P @?= (_5P :| [])
, testCase "enumFromThen1" $ enumFromThen1 LT LT @?= (LT :| [])
, testCase "enumFromThen1" $ enumFromThen1 LT GT @?= (LT :| [GT])
, testCase "enumFromThen1" $ enumFromThen1 GT LT @?= (GT :| [LT])
, testCase "enumFromThen1" $ enumFromThen1 GT EQ @?= (GT :| [EQ, LT])
, testCase "enumFromTo1" $ enumFromTo1 _5P _9P @?= (_5P :| [_6P, _7P, _8P, _9P])
, testCase "enumFromTo1" $ enumFromTo1 _9P _5P @?= (_9P :| [_8P, _7P, _6P, _5P])
, testCase "enumFromTo1" $ enumFromTo1 _5P _5P @?= (_5P :| [])
, testCase "enumFromTo1" $ enumFromTo1 LT LT @?= (LT :| [])
, testCase "enumFromTo1" $ enumFromTo1 LT GT @?= (LT :| [EQ, GT])
, testCase "enumFromTo1" $ enumFromTo1 GT LT @?= (GT :| [EQ, LT])
, testCase "enumFromTo1" $ enumFromTo1 GT EQ @?= (GT :| [EQ])
, testCase "universe1" $ universe1 @?= (LT :| [EQ, GT])
, testCase "universe1R" $ universe1R @?= (GT :| [EQ, LT])
, testCase "universe1R" $ universe1R @?= (GT :| [EQ, LT])
, testCase "enumTo1" $ enumTo1 _4P @?= (_1P :| [_2P, _3P, _4P])
, testCase "enumFrom1" $ enumFrom1 EQ @?= (EQ :| [GT])
, testCase "enumFrom1" $ enumFrom1 GT @?= (GT :| [])
, testCase "enumFrom1R" $ enumFrom1R LT @?= (LT :| [])
, testCase "enumFrom1R" $ enumFrom1R EQ @?= (EQ :| [LT])
, testCase "enumFrom1R" $ enumFrom1R GT @?= (GT :| [EQ, LT])
, testCase "toEnumTraversable" $ toEnumTraversable @Ordering (Just ()) 0 @?= Right (Just LT)
, testCase "toEnumTraversable" $ toEnumTraversable @Ordering (Just ()) 2 @?= Right (Just GT)
, testCase "toEnumTraversable" $ toEnumTraversable @Ordering (Just ()) 10 @?= Left "cap=(0,2):padL: negative fill: would need to truncate the data"
, testCase "toEnumTraversable" $ toEnumTraversable @Ordering (replicate 5 ()) 242 @?= Right [GT, GT, GT, GT, GT]
, testCase "toEnumTraversable" $ toEnumTraversable @Ordering (replicate 5 ()) 243 @?= Left "cap=(0,242):padL: negative fill: would need to truncate the data"
, testCase "toEnumTraversable" $ toEnumTraversable @Ordering (replicate 5 ()) 0 @?= Right [LT, LT, LT, LT, LT]
, testCase "toEnumTraversable" $ toEnumTraversable @Ordering (replicate 5 ()) (-1) @?= Left "calcNextEnum:not defined for negative numbers"
, testCase "toEnumTraversable" $ toEnumTraversable @Ordering (replicate 5 ()) (-123) @?= Left "calcNextEnum:not defined for negative numbers"
, testCase "toEnumList" $ toEnumList @Ordering 14 @?= Right [EQ, EQ, GT]
, testCase "toEnumList" $ toEnumList1 @Ordering 0 @?= Right (LT :| [])
, testCase "toEnumList" $ toEnumList1 @() 0 @?= Right (() :| [])
, testCase "enumlist" $ traverse (fromEnumFoldable <=< toEnumList @PosNeg) [-5 .. 5] @?= Right [-5 .. 5]
, testCase "enumlist" $ map (toEnumList @PosOnly) [-5 .. -1] @?= replicate 5 (Left "calcNextEnum:not defined for negative numbers")
, testCase "enumlist" $ toEnumList @PosOnly 0 @?= Left "zerolr: not defined at zero"
, testCase "enumlist" $ toEnumList @PosOnly 1 @?= Right [AA1]
, testCase "enumlist" $ toEnumList @PosOnly 2 @?= Right [BB1]
, testCase "enumlist" $ toEnumList @PosOnly 3 @?= Right [CC1]
, testCase "enumlist" $ left (const ()) (toEnumList @PosOnly 4) @?= Left ()
, testCase "enumlist" $ toEnumList @PosOnly 5 @?= Right [AA1, AA1]
, testCase "enumlist" $ toEnumList @PosOnly 6 @?= Right [AA1, BB1]
, testCase "enumlist" $ toEnumList @PosOnly 7 @?= Right [AA1, CC1]
, testCase "enumlist" $ left (const ()) (toEnumList @PosOnly 8) @?= Left ()
, testCase "enumlist" $ toEnumList @PosOnly2 0 @?= Left "zerolr: not defined at zero"
, testCase "enumlist" $ left (const ()) (toEnumList @PosOnly2 1) @?= Left ()
, testCase "enumlist" $ toEnumList @PosOnly2 2 @?= Right [AA5]
, testCase "enumlist" $ toEnumList @PosOnly2 123 @?= Right [CC5, CC5, BB5]
, testCase "enumlist" $ map (toEnumList @NegOnly) [1 .. 5] @?= replicate 5 (Left "calcNextEnum:not defined for positive numbers")
, testCase "enumlist" $ toEnumList @NegOnly 0 @?= Left "zerolr: not defined at zero"
, testCase "enumlist" $ toEnumList @NegOnly (-1) @?= Right [CC4]
, testCase "enumlist" $ toEnumList @NegOnly (-2) @?= Right [BB4]
, testCase "enumlist" $ toEnumList @NegOnly (-3) @?= Right [AA4]
, testCase "enumlist" $ left (const ()) (toEnumList @NegOnly (-4)) @?= Left ()
, testCase "enumlist" $ toEnumList @NegOnly (-5) @?= Right [CC4, CC4]
, testCase "enumlist" $ toEnumList @NegOnly (-6) @?= Right [CC4, BB4]
, testCase "enumlist" $ toEnumList @NegOnly (-7) @?= Right [CC4, AA4]
, testCase "enumlist" $ left (const ()) (toEnumList @NegOnly (-8)) @?= Left ()
, testCase "enumlist" $ map (toEnumList @PosNat) [-5 .. -1] @?= replicate 5 (Left "calcNextEnum:not defined for negative numbers")
, testCase "enumlist" $ toEnumList @PosNat 0 @?= Right []
, testCase "enumlist" $ toEnumList @PosNat 1 @?= Right [BB2]
, testCase "enumlist" $ toEnumList @PosNat 2 @?= Right [CC2]
, testCase "enumlist" $ toEnumList @PosNat 3 @?= Right [DD2]
, testCase "enumlist" $ toEnumList @PosNat 4 @?= Right [BB2, AA2]
, testCase "enumlist" $ toEnumList @PosNat 5 @?= Right [BB2, BB2]
, testCase "enumlist" $ map (toEnumList @NegNat) [1 .. 5] @?= replicate 5 (Left "calcNextEnum:not defined for positive numbers")
, testCase "enumlist" $ toEnumList @NegNat 0 @?= Right []
, testCase "enumlist" $ toEnumList @NegNat (-1) @?= Right [CC3]
, testCase "enumlist" $ toEnumList @NegNat (-2) @?= Right [BB3]
, testCase "enumlist" $ toEnumList @NegNat (-3) @?= Right [AA3]
, testCase "enumlist" $ toEnumList @NegNat (-4) @?= Right [CC3, DD3]
, testCase "enumlist" $ toEnumList @NegNat (-5) @?= Right [CC3, CC3]
, testCase "enumlist" $ toEnumList @NegNat (-6) @?= Right [CC3, BB3]
, testCase "enumlist" $ toEnumList @NegNat (-7) @?= Right [CC3, AA3]
, testCase "enumlist" $ toEnumList @NegNat (-8) @?= Right [BB3, DD3]
, testCase "enumlist" $ toEnumList 100 @?= Right [True, True, False, False, True, False, False]
, testCase "enumlist1" $ toEnumList1 100 @?= Right (True :| [True, False, False, True, False, False])
, testCase "fromenum" $ fromEnumFoldable @PosOnly [] @?= Left "zerolr: not defined at zero"
, testCase "fromenum" $ fromEnumFoldable @NegNat [] @?= Right 0
, testCase "fromenum" $ fromEnumFoldable @PosNat [] @?= Right 0
, testCase "fromenum" $ fromEnumFoldable @PosNeg [] @?= Right 0
, testCase "universe1" $ universe1 @Ordering @?= (LT :| [EQ, GT])
, testCase "toEnumList" $ toEnumList @Ordering 0 @?= Right []
, testCase "toEnumList" $ toEnumList @Ordering 1 @?= Right [EQ]
, testCase "toEnumList" $ toEnumList @Ordering 2 @?= Right [GT]
, testCase "toEnumList" $ toEnumList @Ordering 3 @?= Right [EQ, LT]
, testCase "toEnumList" $ toEnumList @Ordering 10 @?= Right [EQ, LT, EQ]
, testCase "toEnumList" $ toEnumList @Ordering 200 @?= Right [GT, EQ, EQ, LT, GT]
, testCase "toEnumList1" $ toEnumList1 @Ordering 200 @?= Right (GT :| [EQ, EQ, LT, GT])
, testCase "toEnumList1" $ toEnumList1 @Ordering 0 @?= Right (LT :| [])
, testCase "toEnumList1" $ toEnumList1 @Ordering 1 @?= Right (EQ :| [])
, testCase "toEnumList1" $ toEnumList1 @Ordering 100 @?= Right (EQ :| [LT, GT, LT, EQ])
, testCase "toEnumList1" $ toEnumList1 @Ordering 27 @?= Right (EQ :| [LT, LT, LT])
, testCase "succ pred traversable" $ iterateT1 succTraversable [LT, LT, LT] @?= N.reverse (iterateT1 predTraversable [GT, GT, GT])
, testCase "succ traversable" $
iterateT1 succTraversable [LT, LT, LT]
@?= ( [LT, LT, LT]
:| [ [LT, LT, EQ]
, [LT, LT, GT]
, [LT, EQ, LT]
, [LT, EQ, EQ]
, [LT, EQ, GT]
, [LT, GT, LT]
, [LT, GT, EQ]
, [LT, GT, GT]
, [EQ, LT, LT]
, [EQ, LT, EQ]
, [EQ, LT, GT]
, [EQ, EQ, LT]
, [EQ, EQ, EQ]
, [EQ, EQ, GT]
, [EQ, GT, LT]
, [EQ, GT, EQ]
, [EQ, GT, GT]
, [GT, LT, LT]
, [GT, LT, EQ]
, [GT, LT, GT]
, [GT, EQ, LT]
, [GT, EQ, EQ]
, [GT, EQ, GT]
, [GT, GT, LT]
, [GT, GT, EQ]
, [GT, GT, GT]
]
)
, testCase "predSafe" $
predSafe LT @?= Nothing
, testCase "predSafe" $
predSafe EQ @?= Just LT
, testCase "predSafe" $
predSafe GT @?= Just EQ
, testCase "predSafe" $
predSafe AA @?= Nothing
, testCase "predSafe" $
predSafe BB @?= Just AA
, testCase "predSafe" $
predSafe EE @?= Just DD
, testCase "succSafe" $
succSafe LT @?= Just EQ
, testCase "succSafe" $
succSafe EQ @?= Just GT
, testCase "succSafe" $
succSafe GT @?= Nothing
, testCase "succSafe" $
succSafe AA @?= Just BB
, testCase "succSafe" $
succSafe DD @?= Just EE
, testCase "succSafe" $
succSafe EE @?= Nothing
, testCase "enumFromThen1" $ enumFromThen1 AA AA @?= AA :| []
, testCase "enumFromThen1" $ enumFromThen1 BB AA @?= BB :| [AA]
, testCase "enumFromThen1" $ enumFromThen1 BB CC @?= BB :| [CC, DD, EE]
, testCase "enumFromThen1" $ enumFromThen1 EE CC @?= EE :| [CC, AA]
, testCase "enumFromTo1" $ enumFromTo1 AA AA @?= AA :| []
, testCase "enumFromTo1" $ enumFromTo1 BB AA @?= BB :| [AA]
, testCase "enumFromTo1" $ enumFromTo1 BB EE @?= BB :| [CC, DD, EE]
, testCase "enumFromTo1" $ enumFromTo1 BB CC @?= BB :| [CC]
, testCase "enumFromTo1" $ enumFromTo1 EE CC @?= EE :| [DD, CC]
, testCase "predSafe" $ predSafe _4P @?= Just _3P
, testCase "universe1" $ universe1 @?= (AA :| [BB, CC, DD, EE])
, testCase "universe1R" $ universe1R @?= (EE :| [DD, CC, BB, AA])
, testCase "universe1" $ universe1 @?= (AA3 :| [BB3, CC3, DD3])
, testCase "universe1R" $ universe1R @?= (DD3 :| [CC3, BB3, AA3])
, testCase "fromEnumFoldable" $
fromEnumFoldable (replicate 5 (maxBound @Int8))
@?= Right 34359738367
, testCase "fromEnumFoldable" $
fromEnumFoldable (replicate 5 (minBound @Int8))
@?= Right (-35723051648)
, testCase "capacity" $
capacity @Int8 (replicate 5 ())
@?= Right (-35723051648, 34359738367)
, testCase "capacity" $
capacity @NegOnly []
@?= Left "capacity: unsupported mx < 0: (-3,-1)"
, testCase "capacity" $
capacity @PosOnly ['x']
@?= Left "capacity: unsupported mn > 0: (1,3)"
, testCase "universeTraversable" $
universeTraversable [EQ]
@?= Right ([LT] :| [[EQ], [GT]])
, testCase "universeTraversable" $
universeTraversable [EQ, EQ]
@?= Right ([LT, LT] :| [[LT, EQ], [LT, GT], [EQ, LT], [EQ, EQ], [EQ, GT], [GT, LT], [GT, EQ], [GT, GT]])
, testCase "universeTraversable" $
universeTraversable [EQ, EQ, EQ]
@?= Right ([LT, LT, LT] :| [[LT, LT, EQ], [LT, LT, GT], [LT, EQ, LT], [LT, EQ, EQ], [LT, EQ, GT], [LT, GT, LT], [LT, GT, EQ], [LT, GT, GT], [EQ, LT, LT], [EQ, LT, EQ], [EQ, LT, GT], [EQ, EQ, LT], [EQ, EQ, EQ], [EQ, EQ, GT], [EQ, GT, LT], [EQ, GT, EQ], [EQ, GT, GT], [GT, LT, LT], [GT, LT, EQ], [GT, LT, GT], [GT, EQ, LT], [GT, EQ, EQ], [GT, EQ, GT], [GT, GT, LT], [GT, GT, EQ], [GT, GT, GT]])
, testCase "universeTraversable" $
universeTraversable [(), (), ()]
@?= Right ([(), (), ()] :| [])
, testCase "capacity" $
capacity @PosNeg (replicate 5 ())
@?= Right (-242, 242)
, testCase "capacity" $
capacity @PosNeg (replicate 3 ())
@?= Right (-26, 26)
, testCase "universeTraversable" $
universeTraversable [AA, BB, CC]
@?= Right ([AA, AA, AA] :| [[AA, AA, BB], [AA, AA, CC], [AA, BB, AA], [AA, BB, BB], [AA, BB, CC], [AA, CC, AA], [AA, CC, BB], [AA, CC, CC], [BB, AA, AA], [BB, AA, BB], [BB, AA, CC], [BB, BB, AA], [BB, BB, BB], [BB, BB, CC], [BB, CC, AA], [BB, CC, BB], [BB, CC, CC], [CC, AA, AA], [CC, AA, BB], [CC, AA, CC], [CC, BB, AA], [CC, BB, BB], [CC, BB, CC], [CC, CC, AA], [CC, CC, BB], [CC, CC, CC], [CC, CC, DD], [CC, CC, EE], [CC, DD, CC], [CC, DD, DD], [CC, DD, EE], [CC, EE, CC], [CC, EE, DD], [CC, EE, EE], [DD, CC, CC], [DD, CC, DD], [DD, CC, EE], [DD, DD, CC], [DD, DD, DD], [DD, DD, EE], [DD, EE, CC], [DD, EE, DD], [DD, EE, EE], [EE, CC, CC], [EE, CC, DD], [EE, CC, EE], [EE, DD, CC], [EE, DD, DD], [EE, DD, EE], [EE, EE, CC], [EE, EE, DD], [EE, EE, EE]])
, testCase "capacity" $
capacity @NegNat (replicate 3 ())
@?= Right (-63, 0)
, testCase "universeTraversable" $
universeTraversable [AA3, AA3, AA3]
@?= Right ([AA3, AA3, AA3] :| [[AA3, AA3, BB3], [AA3, AA3, CC3], [AA3, AA3, DD3], [AA3, BB3, AA3], [AA3, BB3, BB3], [AA3, BB3, CC3], [AA3, BB3, DD3], [AA3, CC3, AA3], [AA3, CC3, BB3], [AA3, CC3, CC3], [AA3, CC3, DD3], [AA3, DD3, AA3], [AA3, DD3, BB3], [AA3, DD3, CC3], [AA3, DD3, DD3], [BB3, AA3, AA3], [BB3, AA3, BB3], [BB3, AA3, CC3], [BB3, AA3, DD3], [BB3, BB3, AA3], [BB3, BB3, BB3], [BB3, BB3, CC3], [BB3, BB3, DD3], [BB3, CC3, AA3], [BB3, CC3, BB3], [BB3, CC3, CC3], [BB3, CC3, DD3], [BB3, DD3, AA3], [BB3, DD3, BB3], [BB3, DD3, CC3], [BB3, DD3, DD3], [CC3, AA3, AA3], [CC3, AA3, BB3], [CC3, AA3, CC3], [CC3, AA3, DD3], [CC3, BB3, AA3], [CC3, BB3, BB3], [CC3, BB3, CC3], [CC3, BB3, DD3], [CC3, CC3, AA3], [CC3, CC3, BB3], [CC3, CC3, CC3], [CC3, CC3, DD3], [CC3, DD3, AA3], [CC3, DD3, BB3], [CC3, DD3, CC3], [CC3, DD3, DD3], [DD3, AA3, AA3], [DD3, AA3, BB3], [DD3, AA3, CC3], [DD3, AA3, DD3], [DD3, BB3, AA3], [DD3, BB3, BB3], [DD3, BB3, CC3], [DD3, BB3, DD3], [DD3, CC3, AA3], [DD3, CC3, BB3], [DD3, CC3, CC3], [DD3, CC3, DD3], [DD3, DD3, AA3], [DD3, DD3, BB3], [DD3, DD3, CC3], [DD3, DD3, DD3]])
, testCase "fromEnumFoldable1 universeTraversable" $
let m = universeTraversable [AA3, AA3, AA3]
z = join $ (traverse . traverse) fromEnumFoldable m
in z @?= Right (-63 :| [-62 .. 0])
, testCase "fromEnumFoldable1 universeTraversable" $
let m = universeTraversable [AA, AA, AA]
z = join $ (traverse . traverse) fromEnumFoldable m
in z @?= Right (-26 :| [-25 .. 26])
, testCase "universeTraversable" $
universeTraversable ([] :: [Ordering])
@?= Right ([] :| [])
, testCase "capacity" $
capacity @Ordering []
@?= Right (0, 0)
, testCase "integerToEnumSafe" $
integerToEnumSafe @() 1
@?= Left "integerToEnumSafe:overflow where 1 not in range [0..0]"
, testCase "integerToEnumSafe" $
integerToEnumSafe @() 0
@?= Right ()
, testCase "integerToEnumSafe" $
integerToEnumSafe @PosNeg 3
@?= Left "integerToEnumSafe:overflow where 3 not in range [-2..2]"
, testCase "integerToEnumSafe" $
integerToEnumSafe @PosNeg (-3)
@?= Left "integerToEnumSafe:underflow where -3 not in range [-2..2]"
, testCase "integerToEnumSafe" $
integerToEnumSafe @PosNeg (-2)
@?= Right AA
, testCase "integerToIntSafe" $
integerToIntSafe (fromIntegral (minBound :: Int))
@?= Right (-9223372036854775808)
, testCase "integerToIntSafe" $
integerToIntSafe (-1 + fromIntegral (minBound :: Int))
@?= Left "integerToEnumSafe:underflow where -9223372036854775809 not in range [-9223372036854775808..9223372036854775807]"
, testCase "integerToIntSafe" $
integerToIntSafe (fromIntegral (maxBound :: Int))
@?= Right 9223372036854775807
, testCase "integerToIntSafe" $
integerToIntSafe (1 + fromIntegral (maxBound :: Int))
@?= Left "integerToEnumSafe:overflow where 9223372036854775808 not in range [-9223372036854775808..9223372036854775807]"
, testCase "universe1" $
universe1 @() @?= () :| []
, testCase "universe1R" $
universe1R @() @?= () :| []
, testCase "enumFrom1" $
enumFrom1 @() () @?= () :| []
, testCase "enumFrom1R" $
enumFrom1R @() () @?= () :| []
, testCase "enumFromTo1" $
enumFromTo1 @() () () @?= () :| []
, testCase "enumTo1" $
enumTo1 @() () @?= () :| []
, testCase "enumFromThen1" $
enumFromThen1 @() () () @?= () :| []
, testCase "enumFromThenTo1" $
enumFromThenTo1 @() () () () @?= () :| []
, testCase "enumFrom1" $
enumFrom1 @PosNeg DD @?= DD :| [EE]
, testCase "enumFrom1R" $
enumFrom1R @PosNeg DD @?= DD :| [CC, BB, AA]
, testCase "enumFromTo1" $
enumFromTo1 @PosNeg DD BB @?= DD :| [CC, BB]
, testCase "enumTo1" $
enumTo1 @PosNeg AA @?= AA :| []
, testCase "enumFromThen1" $
enumFromThen1 @PosNeg AA CC @?= AA :| [CC, EE]
, testCase "enumFromThenTo1" $
enumFromThenTo1 @PosNeg AA AA BB @?= AA :| []
, testCase "enumFromThenTo1" $
enumFromThenTo1 @PosNeg EE DD DD @?= EE :| [DD]
, testCase "enumFromThenTo1" $
enumFromThenTo1 @PosNeg EE DD BB @?= EE :| [DD, CC, BB]
]
data PosNeg = AA | BB | CC | DD | EE deriving stock (Bounded, Show, Eq)
instance Enum PosNeg where
toEnum (-2) = AA
toEnum (-1) = BB
toEnum 0 = CC
toEnum 1 = DD
toEnum 2 = EE
toEnum _ = error "bad toEnum PosNeg"
fromEnum AA = -2
fromEnum BB = -1
fromEnum CC = 0
fromEnum DD = 1
fromEnum EE = 2
data PosNat = AA2 | BB2 | CC2 | DD2 deriving stock (Bounded, Show, Eq)
instance Enum PosNat where
toEnum 0 = AA2
toEnum 1 = BB2
toEnum 2 = CC2
toEnum 3 = DD2
toEnum _ = error "bad toEnum PosNat"
fromEnum AA2 = 0
fromEnum BB2 = 1
fromEnum CC2 = 2
fromEnum DD2 = 3
data NegNat = AA3 | BB3 | CC3 | DD3 deriving stock (Bounded, Show, Eq)
instance Enum NegNat where
toEnum (-3) = AA3
toEnum (-2) = BB3
toEnum (-1) = CC3
toEnum 0 = DD3
toEnum _ = error "bad toEnum NegNat"
fromEnum AA3 = -3
fromEnum BB3 = -2
fromEnum CC3 = -1
fromEnum DD3 = 0
data PosOnly = AA1 | BB1 | CC1 deriving stock (Bounded, Show, Eq)
instance Enum PosOnly where
toEnum 1 = AA1
toEnum 2 = BB1
toEnum 3 = CC1
toEnum _ = error "bad toEnum PosOnly"
fromEnum AA1 = 1
fromEnum BB1 = 2
fromEnum CC1 = 3
data PosOnly2 = AA5 | BB5 | CC5 deriving stock (Bounded, Show, Eq)
instance Enum PosOnly2 where
toEnum 2 = AA5
toEnum 3 = BB5
toEnum 4 = CC5
toEnum _ = error "bad toEnum PosOnly2"
fromEnum AA5 = 2
fromEnum BB5 = 3
fromEnum CC5 = 4
data NegOnly = AA4 | BB4 | CC4 deriving stock (Bounded, Show, Eq)
instance Enum NegOnly where
toEnum (-3) = AA4
toEnum (-2) = BB4
toEnum (-1) = CC4
toEnum _ = error "bad toEnum NegOnly"
fromEnum AA4 = -3
fromEnum BB4 = -2
fromEnum CC4 = -1