packages feed

named-sop 0.1.0.1 → 0.2.0.0

raw patch · 6 files changed

+261/−30 lines, 6 filesdep +named-sopdep +tastydep +tasty-hunitdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: named-sop, tasty, tasty-hunit

Dependency ranges changed: base

API changes (from Hackage documentation)

- Data.NamedSOP.Map: instance Data.NamedSOP.Map.ShowMap xs => GHC.Show.Show (Data.NamedSOP.Map.NMap xs)
+ Data.NamedSOP.Generic: instance Data.NamedSOP.Generic.GenProduct GHC.Generics.U1
+ Data.NamedSOP.Generic: instance Data.NamedSOP.Generic.GenProductN GHC.Generics.U1
+ Data.NamedSOP.Generic: instance Data.NamedSOP.Generic.GenSum GHC.Generics.V1
+ Data.NamedSOP.Map: instance GHC.Classes.Eq (Data.NamedSOP.Map.NMap '[])
+ Data.NamedSOP.Map: instance GHC.Classes.Ord (Data.NamedSOP.Map.NMap '[])
+ Data.NamedSOP.Map: instance forall s (xs :: [Data.NamedSOP.Type.Mapping s *]). Data.NamedSOP.Map.ShowMap xs => GHC.Show.Show (Data.NamedSOP.Map.NMap xs)
+ Data.NamedSOP.Map: instance forall s v (xs :: [Data.NamedSOP.Type.Mapping s *]) (k :: s). (GHC.Classes.Eq v, GHC.Classes.Eq (Data.NamedSOP.Map.NMap xs)) => GHC.Classes.Eq (Data.NamedSOP.Map.NMap ((k 'Data.NamedSOP.Type.:-> v) : xs))
+ Data.NamedSOP.Map: instance forall s v (xs :: [Data.NamedSOP.Type.Mapping s *]) (k :: s). (GHC.Classes.Ord v, GHC.Classes.Ord (Data.NamedSOP.Map.NMap xs)) => GHC.Classes.Ord (Data.NamedSOP.Map.NMap ((k 'Data.NamedSOP.Type.:-> v) : xs))
+ Data.NamedSOP.Sum: instance GHC.Classes.Eq (Data.NamedSOP.Sum.NSum '[])
+ Data.NamedSOP.Sum: instance GHC.Classes.Ord (Data.NamedSOP.Sum.NSum '[])
+ Data.NamedSOP.Sum: instance forall s v (xs :: [Data.NamedSOP.Type.Mapping s *]) (k :: s). (GHC.Classes.Eq v, GHC.Classes.Eq (Data.NamedSOP.Sum.NSum xs)) => GHC.Classes.Eq (Data.NamedSOP.Sum.NSum ((k 'Data.NamedSOP.Type.:-> v) : xs))
+ Data.NamedSOP.Sum: instance forall s v (xs :: [Data.NamedSOP.Type.Mapping s *]) (k :: s). (GHC.Classes.Ord v, GHC.Classes.Ord (Data.NamedSOP.Sum.NSum xs)) => GHC.Classes.Ord (Data.NamedSOP.Sum.NSum ((k 'Data.NamedSOP.Type.:-> v) : xs))
- Data.NamedSOP.Map: data NMap :: [Mapping Symbol Type] -> Type
+ Data.NamedSOP.Map: data NMap :: [Mapping s Type] -> Type
- Data.NamedSOP.Map: unionMap :: forall xs ys. (SingI xs, SingI ys) => (NMap xs, NMap ys) -> NMap (Union xs ys)
+ Data.NamedSOP.Map: unionMap :: forall s (xs :: [Mapping s *]) (ys :: [Mapping s *]). (SingI xs, SingI ys, SOrd s) => (NMap xs, NMap ys) -> NMap (Union xs ys)
- Data.NamedSOP.Map: ununionMap :: forall xs ys. (SingI xs, SingI ys) => NMap (Union xs ys) -> (NMap xs, NMap ys)
+ Data.NamedSOP.Map: ununionMap :: forall s (xs :: [Mapping s *]) (ys :: [Mapping s *]). (SingI xs, SingI ys, SOrd s) => NMap (Union xs ys) -> (NMap xs, NMap ys)
- Data.NamedSOP.Sum: [NSumThis] :: v -> NSum ((k :-> v) : xs)
+ Data.NamedSOP.Sum: [NSumThis] :: forall k v xs. v -> NSum ((k :-> v) : xs)
- Data.NamedSOP.Sum: data NSum :: [Mapping Symbol Type] -> Type
+ Data.NamedSOP.Sum: data NSum :: [Mapping s Type] -> Type
- Data.NamedSOP.Sum: unionSum :: forall xs ys. (SingI xs, SingI ys) => Either (NSum xs) (NSum ys) -> NSum (Union xs ys)
+ Data.NamedSOP.Sum: unionSum :: forall s (xs :: [Mapping s *]) (ys :: [Mapping s *]). (SingI xs, SingI ys, SOrd s) => Either (NSum xs) (NSum ys) -> NSum (Union xs ys)
- Data.NamedSOP.Sum: ununionSum :: forall xs ys. (SingI xs, SingI ys) => NSum (Union xs ys) -> Either (NSum xs) (NSum ys)
+ Data.NamedSOP.Sum: ununionSum :: forall s (xs :: [Mapping s *]) (ys :: [Mapping s *]). (SingI xs, SingI ys, SOrd s) => NSum (Union xs ys) -> Either (NSum xs) (NSum ys)

Files

CHANGELOG.md view
@@ -1,3 +1,13 @@+# 0.2.0.0++- Made NMap and NSum polymorphic over the kind of the key.  (Perhaps+  'Natural' keys would be useful as well.)  This is a breaking API+  change, because the qualifier for the kind of the key must go before+  the qualifier for the typelevel lists, potentially breaking+  TypeApplication uses.+- Add Eq and Ord instances for NMap and NSum+- Add a testsuite+ # 0.1.0.1  Quickfix for an oversight in the `uninsertSum` function that broke
named-sop.cabal view
@@ -1,5 +1,5 @@ name:                named-sop-version:             0.1.0.1+version:             0.2.0.0 category:            Data  homepage:            https://github.com/sjsch/named-sop@@ -47,3 +47,14 @@   hs-source-dirs:      src   default-language:    Haskell2010   ghc-options:         -Wall -Werror=incomplete-patterns++test-suite named-sop-spec+  type:                exitcode-stdio-1.0+  main-is:             Tests.hs+  hs-source-dirs:      test+  build-depends:       base+                     , named-sop+                     , tasty+                     , tasty-hunit+  default-language:    Haskell2010+  ghc-options:         -Wall -Werror=incomplete-patterns                     
src/Data/NamedSOP/Generic.hs view
@@ -48,6 +48,11 @@   genProduct'  = genProduct' . unM1   specProduct' = M1 . specProduct' +instance GenProduct U1 where+  type GProduct U1 = '[]+  genProduct' U1 = NMapEmpty+  specProduct' NMapEmpty = U1+ instance GenProduct (S1 ('MetaSel ('Just n) _a _b _c) (Rec0 t)) where   type GProduct (S1 ( 'MetaSel ( 'Just n) _a _b _c) (Rec0 t)) = '[n ':-> t]   genProduct' (M1 (K1 c)) = NMapExt c NMapEmpty@@ -73,6 +78,14 @@   genProductN' :: Sing n -> f a -> NMap (GProductN n f)   specProductN' :: Sing n -> NMap (GProductN n f) -> f a +instance GenProductN U1 where+  type GProductN n U1 = '[]+  type GProductS U1 = 0+  sGProductS = SNat+  sGProductN _ = SNil+  genProductN' _ U1 = NMapEmpty+  specProductN' _ NMapEmpty = U1+ instance GenProductN (S1 ('MetaSel 'Nothing _a _b _c) (Rec0 t)) where   type GProductN n (S1 ( 'MetaSel 'Nothing _a _b _c) (Rec0 t)) = '[Mappend "_" (Show_ n) ':-> t]   type GProductS (S1 ( 'MetaSel 'Nothing _a _b _c) (Rec0 t)) = 1@@ -97,7 +110,7 @@         (x, y) =             withSingI sm1               $ withSingI sm2-              $ ununionMap @(GProductN n f) @(GProductN (n + GProductS f) g) m+              $ ununionMap @_ @(GProductN n f) @(GProductN (n + GProductS f) g) m     in  specProductN' sn x :*: specProductN' (sn %+ sGProductS @f) y  class GenSum (f :: * -> *) where@@ -110,6 +123,11 @@   genSum'  = genSum' . unM1   specSum' = M1 . specSum' +instance GenSum V1 where+  type GSum V1 = '[]+  genSum' _ = error "unreachable"+  specSum' _ = error "unreachable"+ instance GenProduct f => GenSum (C1 ('MetaCons n _a 'True) f) where   type GSum (C1 ( 'MetaCons n _a 'True) f) = '[Mappend "_" n ':-> NMap (GProduct f)]   genSum' (M1 x) = NSumThis (genProduct' x)@@ -125,9 +143,9 @@ instance ( SingI (GSum f), SingI (GSum g)          , GenSum f, GenSum g) => GenSum (f :+: g) where   type GSum (f :+: g) = Union (GSum f) (GSum g)-  genSum' (L1 x) = unionSum @(GSum f) @(GSum g) (Left (genSum' x))-  genSum' (R1 x) = unionSum @(GSum f) @(GSum g) (Right (genSum' x))-  specSum' m = case ununionSum @(GSum f) @(GSum g) m of+  genSum' (L1 x) = unionSum @_ @(GSum f) @(GSum g) (Left (genSum' x))+  genSum' (R1 x) = unionSum @_ @(GSum f) @(GSum g) (Right (genSum' x))+  specSum' m = case ununionSum @_ @(GSum f) @(GSum g) m of     Left  x -> L1 (specSum' x)     Right y -> R1 (specSum' y) @@ -154,11 +172,13 @@ -- constructors into an 'NSum' of 'NMap's.  All constructor names will -- be prefixed with @_@ to allow for the use of @-XOverloadedLabels@. ----- >>> data A = C { a :: Int, b :: Bool } | D Int Bool deriving (Generic)+-- >>> data A = C { a :: Int, b :: Bool } | D Int Bool | E String+-- >>>   deriving (Generic) -- >>> :t genSum (C 3 True) -- NSum --  '[ "_C" ':-> NMap '[ "a" ':-> Int, "b" ':-> Bool],---     "_D" ':-> NMap '[ "_1" ':-> Int, "_2" ':-> Bool]]+--     "_D" ':-> NMap '[ "_1" ':-> Int, "_2" ':-> Bool],+--     "_E" ':-> NMap '[ "_1" ':-> String ]] genSum :: (Generic a, GenSum (Rep a)) => a -> NSum (GSum (Rep a)) genSum = genSum' . from 
src/Data/NamedSOP/Map.hs view
@@ -1,7 +1,8 @@ {-# LANGUAGE DataKinds           #-}+{-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE GADTs               #-}-{-# LANGUAGE KindSignatures      #-}+{-# LANGUAGE PolyKinds           #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications    #-}@@ -31,7 +32,7 @@ -- -- > type A = NMap '[ "a" ':-> Int, "b" ':-> Bool ] -- > data A = A { a :: Int, b :: Bool }-data NMap :: [Mapping Symbol Type] -> Type where+data NMap :: [Mapping s Type] -> Type where   NMapEmpty :: NMap '[]   NMapExt :: forall k v xs. v -> NMap xs -> NMap ((k ':-> v) : xs) @@ -56,12 +57,26 @@ instance ShowMap xs => Show (NMap xs) where   show xs = "{ " ++ showMap xs ++ " }" +instance Eq (NMap '[]) where+  NMapEmpty == NMapEmpty = True++instance (Eq v, Eq (NMap xs)) => Eq (NMap ((k ':-> v) ': xs)) where+  (NMapExt x xs) == (NMapExt y ys) = x == y && xs == ys++instance Ord (NMap '[]) where+  compare NMapEmpty NMapEmpty = EQ++instance (Ord v, Ord (NMap xs)) => Ord (NMap ((k ':-> v) ': xs)) where+  compare (NMapExt x xs) (NMapExt y ys) = case compare x y of+    EQ -> compare xs ys+    o  -> o+ appendMap :: NMap xs -> NMap ys -> NMap (xs ++ ys) appendMap NMapEmpty ys      = ys appendMap (NMapExt x xs) ys = NMapExt x (appendMap xs ys) -insertMap ::-     Sing (k ':-> v) -> Sing xs -> v -> NMap xs -> NMap (Insert (k ':-> v) xs)+insertMap :: forall s k v (xs :: [Mapping s *]). SOrd s+  => Sing (k ':-> v) -> Sing xs -> v -> NMap xs -> NMap (Insert (k ':-> v) xs) insertMap _ _ x NMapEmpty = NMapExt x NMapEmpty insertMap sxk (SCons syk sys) x ys@(NMapExt y ys') =   case sCompare sxk syk of@@ -69,7 +84,8 @@     SEQ -> NMapExt x ys     SGT -> NMapExt y (insertMap sxk sys x ys') -sortMap :: Sing xs -> NMap xs -> NMap (Sort xs)+sortMap :: forall s (xs :: [Mapping s *]). SOrd s+  => Sing xs -> NMap xs -> NMap (Sort xs) sortMap _ NMapEmpty = NMapEmpty sortMap (SCons sx sxs) (NMapExt x xs) =   insertMap sx (sSort sxs) x (sortMap sxs xs)@@ -85,7 +101,7 @@ -- This function takes a tuple as an argument so that it is symmetric -- with `ununionMap`. unionMap ::-     forall xs ys. (SingI xs, SingI ys)+     forall s (xs :: [Mapping s *]) (ys :: [Mapping s *]). (SingI xs, SingI ys, SOrd s)   => (NMap xs, NMap ys)   -> NMap (Union xs ys) unionMap (xs, ys) = sortMap (sing @xs %++ sing @ys) (appendMap xs ys)@@ -97,7 +113,8 @@   let (a, b) = splitMap sxs sys xs   in (NMapExt x a, b) -uninsertMap :: forall k v xs. Sing (k ':-> v) -> Sing xs -> NMap (Insert (k ':-> v) xs) -> (v, NMap xs)+uninsertMap :: forall s k v (xs :: [Mapping s *]). SOrd s+  => Sing (k ':-> v) -> Sing xs -> NMap (Insert (k ':-> v) xs) -> (v, NMap xs) uninsertMap _ SNil (NMapExt v NMapEmpty) = (v, NMapEmpty) uninsertMap sx@(SMapping sk) (SCons (SMapping sk') sxs) (NMapExt v vs) = case sCompare sk sk' of   SLT -> (v, vs)@@ -106,7 +123,8 @@         in (v', NMapExt v vs') uninsertMap _ (SCons _ _) NMapEmpty = error "unreachable" -unsortMap :: forall xs. Sing xs -> NMap (Sort xs) -> NMap xs+unsortMap :: forall s (xs :: [Mapping s *]). SOrd s+  => Sing xs -> NMap (Sort xs) -> NMap xs unsortMap SNil NMapEmpty = NMapEmpty unsortMap (SCons sx@(SMapping _) sxs) vs =   let (v', vs') = uninsertMap sx (sSort sxs) vs@@ -114,14 +132,15 @@  -- | Split a sorted 'NMap' into two arbitrary (and potentially -- unsorted) submaps.  Conveniently select the submaps to split into--- using @-XTypeApplications@.+-- using @-XTypeApplications@.  (Note the empty type argument for the+-- key kind). -- -- >>> m :: NMap '[ "a" ':-> Int, "b" ':-> Bool, "c" ':-> String ] -- >>> m = NMapExt 1 (NMapExt True (NMapExt "hello" NMapEmpty))--- >>> ununionMap @'[ "b" ':-> Bool, "a" ':-> Int ] @'[ "c" ':-> String ] m+-- >>> ununionMap @_ @'[ "b" ':-> Bool, "a" ':-> Int ] @'[ "c" ':-> String ] m -- ({ b :-> True, a :-> 1 },{ c :-> "hello" })-ununionMap :: forall xs ys. (SingI xs, SingI ys) =>-  NMap (Union xs ys) -> (NMap xs, NMap ys)+ununionMap :: forall s (xs :: [Mapping s *]) (ys :: [Mapping s *]). (SingI xs, SingI ys, SOrd s)+  => NMap (Union xs ys) -> (NMap xs, NMap ys) ununionMap vs = splitMap sxs sys (unsortMap (sxs %++ sys) vs)   where     sxs = sing @xs
src/Data/NamedSOP/Sum.hs view
@@ -2,8 +2,8 @@ {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE FlexibleInstances   #-} {-# LANGUAGE GADTs               #-}-{-# LANGUAGE KindSignatures      #-} {-# LANGUAGE OverloadedStrings   #-}+{-# LANGUAGE PolyKinds           #-} {-# LANGUAGE RankNTypes          #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications    #-}@@ -32,8 +32,8 @@ -- -- > type A = NSum '[ "B" ':-> Int, "C" ':-> Bool ] -- > data A = B Int | C Bool-data NSum :: [Mapping Symbol Type] -> Type where-  NSumThis :: v -> NSum ((k ':-> v) ': xs)+data NSum :: [Mapping s Type] -> Type where+  NSumThis :: forall k v xs. v -> NSum ((k ':-> v) ': xs)   NSumThat :: forall x xs. NSum xs -> NSum (x ': xs)  instance {-# OVERLAPPABLE #-} Show (NSum '[]) where@@ -44,13 +44,31 @@   show (NSumThis v)  = symbolVal (Proxy :: Proxy k) ++ " :-> " ++ show v   show (NSumThat vs) = show vs +instance Eq (NSum '[]) where+  _ == _ = True++instance (Eq v, Eq (NSum xs)) => Eq (NSum ((k ':-> v) ': xs)) where+  (NSumThis x ) == (NSumThis y ) = x == y+  (NSumThat xs) == (NSumThat ys) = xs == ys+  _             == _             = False++instance Ord (NSum '[]) where+  compare _ _ = EQ++instance (Ord v, Ord (NSum xs)) => Ord (NSum ((k ':-> v) ': xs)) where+  compare (NSumThis x ) (NSumThis y ) = compare x y+  compare (NSumThat xs) (NSumThat ys) = compare xs ys+  compare (NSumThis _ ) (NSumThat _ ) = GT+  compare (NSumThat _ ) (NSumThis _ ) = LT+ appendSum :: Sing xs -> Sing ys -> Either (NSum xs) (NSum ys) -> NSum (xs ++ ys) appendSum _ _ (Left (NSumThis x)) = NSumThis x appendSum (SCons _ sxs) sys (Left (NSumThat xs)) = NSumThat (appendSum sxs sys (Left xs)) appendSum SNil _ (Right ys) = ys appendSum (SCons (_ :: Sing x) sxs) sys (Right ys) = NSumThat @x (appendSum sxs sys (Right ys)) -insertSum :: Sing (k ':-> v) -> Sing xs -> Either v (NSum xs) -> NSum (Insert (k ':-> v) xs)+insertSum :: forall s k v (xs :: [Mapping s *]). SOrd s =>+  Sing (k ':-> v) -> Sing xs -> Either v (NSum xs) -> NSum (Insert (k ':-> v) xs) insertSum _ SNil (Left v) = NSumThis v insertSum sxk (SCons syk sys) (Left v) =   case sCompare sxk syk of@@ -65,7 +83,7 @@     NSumThat v' -> NSumThat (insertSum sxk sys (Right v')) insertSum _ SNil (Right _) = error "unreachable" -sortSum :: Sing xs -> NSum xs -> NSum (Sort xs)+sortSum :: forall s (xs :: [Mapping s *]). SOrd s => Sing xs -> NSum xs -> NSum (Sort xs) sortSum SNil _                      = error "unreachable" sortSum (SCons sx sxs) (NSumThis v) = insertSum sx (sSort sxs) (Left v) sortSum (SCons sx@(SMapping _) sxs) (NSumThat vs) =@@ -84,7 +102,7 @@ -- 'Data.NamedSOP.Map.NMapEmpty', and 'Data.NamedSOP.Map.unionMap', it -- is a semiring. unionSum ::-     forall xs ys. (SingI xs, SingI ys)+     forall s (xs :: [Mapping s *]) (ys :: [Mapping s *]). (SingI xs, SingI ys, SOrd s)   => Either (NSum xs) (NSum ys)   -> NSum (Union xs ys) unionSum xs = sortSum (sing @xs %++ sing @ys) (appendSum (sing @xs) (sing @ys) xs)@@ -99,7 +117,8 @@     Left x  -> Left (NSumThat x)     Right x -> Right x -uninsertSum :: forall k v xs. Sing (k ':-> v) -> Sing xs+uninsertSum :: forall s k v (xs :: [Mapping s *]). SOrd s+  => Sing (k ':-> v) -> Sing xs   -> NSum (Insert (k ':-> v) xs) -> Either v (NSum xs) uninsertSum _ SNil (NSumThis v) = Left v uninsertSum _ SNil (NSumThat v) = Right v@@ -114,7 +133,8 @@           Left x  -> Left x           Right x -> Right (NSumThat x) -unsortSum :: forall xs. Sing xs -> NSum (Sort xs) -> NSum xs+unsortSum :: forall s (xs :: [Mapping s *]). SOrd s+  => Sing xs -> NSum (Sort xs) -> NSum xs unsortSum SNil _ = error "unreachable" unsortSum (SCons sx@(SMapping _) sxs) v =   case uninsertSum sx (sSort sxs) v of@@ -126,10 +146,10 @@ -- -- >>> s :: NSum '[ "A" ':-> Int, "B" ':-> Bool, "C" ':-> String ] -- >>> s = NSumThat (NSumThis True) -- Select the "B" field.--- >>> ununionSum @'[ "B" ':-> Bool, "A" ':-> Int ] @'[ "C" ':-> String ] s+-- >>> ununionSum @_ @'[ "B" ':-> Bool, "A" ':-> Int ] @'[ "C" ':-> String ] s -- Left (B :-> True)-ununionSum :: forall xs ys. (SingI xs, SingI ys) =>-  NSum (Union xs ys) -> Either (NSum xs) (NSum ys)+ununionSum :: forall s (xs :: [Mapping s *]) (ys :: [Mapping s *]). (SingI xs, SingI ys, SOrd s)+  => NSum (Union xs ys) -> Either (NSum xs) (NSum ys) ununionSum vs = splitSum sxs sys (unsortSum (sxs %++ sys) vs)   where     sxs = sing @xs
+ test/Tests.hs view
@@ -0,0 +1,151 @@+{-# LANGUAGE TypeOperators         #-}+{-# LANGUAGE TypeApplications         #-}+{-# LANGUAGE DataKinds         #-}+{-# LANGUAGE DeriveGeneric     #-}+{-# LANGUAGE EmptyDataDeriving #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE MonoLocalBinds    #-}+{-# LANGUAGE PolyKinds         #-}++import           Control.Monad+import           GHC.Generics+import           Test.Tasty+import           Test.Tasty.HUnit++import           Data.NamedSOP.Generic+import           Data.NamedSOP.Map+import           Data.NamedSOP.Sum++main :: IO ()+main = defaultMain tests++testGenSpecProd :: ( Generic a+                   , GenProduct (Rep a)+                   , Eq a+                   , Eq (NMap (GProduct (Rep a)))+                   , Show a+                   , Show (NMap (GProduct (Rep a)))) =>+  [Char] -> a -> NMap (GProduct (Rep a)) -> [TestTree]+testGenSpecProd s a b =+  [ testCase ("Generalize " ++ s) $+    genProduct a @?= b+  , testCase ("Specialize " ++ s) $+    specProduct b @?= a+  ]+++testGenSpecSum :: ( Generic a+                   , GenSum (Rep a)+                   , Eq a+                   , Eq (NSum (GSum (Rep a)))+                   , Show a+                   , Show (NSum (GSum (Rep a)))) =>+  [Char] -> a -> NSum (GSum (Rep a)) -> [TestTree]+testGenSpecSum s a b =+  [ testCase ("Generalize " ++ s) $+    genSum a @?= b+  , testCase ("Specialize " ++ s) $+    specSum b @?= a+  ]++tests :: TestTree+tests = testGroup "Unit tests" [isoTests, unionTests]++data EmptyP = EmptyP+  deriving (Eq, Ord, Show, Generic)++data UnaryP a = UnaryP a+  deriving (Eq, Ord, Show, Generic)++data Size2P a b = Size2P a b+  deriving (Eq, Ord, Show, Generic)++data RecordP = RecordP { recordPA :: Int, recordPB :: String }+  deriving (Eq, Ord, Show, Generic)++data EmptyS+  deriving (Eq, Ord, Show, Generic)++data UnaryS a = UnaryS a+  deriving (Eq, Ord, Show, Generic)++data Size2S a b = Size2SA a+                | Size2SB b+  deriving (Eq, Ord, Show, Generic)++data RecordS = RecordSA { recordSAA :: Int }+             | RecordSB { recordSBA :: Bool, recordSBB :: String }+  deriving (Eq, Ord, Show, Generic)++isoTests :: TestTree+isoTests = testGroup "Generic isomorphisms" $ join $+  [ testGenSpecProd "empty product"+    EmptyP+    NMapEmpty+  , testGenSpecProd "unary product"+    (UnaryP True)+    (NMapExt @"_1" True NMapEmpty)+  , testGenSpecProd "size-2 product"+    (Size2P True "hello")+    (NMapExt @"_1" True (NMapExt @"_2" "hello" NMapEmpty))+  , testGenSpecProd "record product"+    (RecordP { recordPA = 1, recordPB = "hello" })+    (NMapExt @"recordPA" 1 (NMapExt @"recordPB" "hello" NMapEmpty))+  , testGenSpecSum "empty sum"+    (undefined :: EmptyS)+    (undefined :: NSum '[])+  , testGenSpecSum "unary sum"+    (UnaryS True)+    (NSumThis @"_UnaryS" (NMapExt @"_1" True NMapEmpty))+  , testGenSpecSum "size-2 sum, 1st branch"+    (Size2SA True :: Size2S Bool String)+    (NSumThis @"_Size2SA" (NMapExt @"_1" True NMapEmpty))+  , testGenSpecSum "size-2 sum, 2nd branch"+    (Size2SB "hello" :: Size2S Bool String)+    (NSumThat (NSumThis @"_Size2SB" (NMapExt @"_1" "hello" NMapEmpty)))+  , testGenSpecSum "sum of records, 1st branch"+    (RecordSA { recordSAA = 1 })+    (NSumThis @"_RecordSA" (NMapExt @"recordSAA" 1 NMapEmpty))+  , testGenSpecSum "sum of records, 2nd branch"+    (RecordSB { recordSBA = True, recordSBB = "hello" })+    (NSumThat (NSumThis @"_RecordSB"+               (NMapExt @"recordSBA" True+                (NMapExt @"recordSBB" "hello" NMapEmpty))))+  ]++unionTests :: TestTree+unionTests = testGroup "Union/ununion operations"+  [ testCase "Union of products" $+    unionMap+    ((NMapExt @"c" True (NMapExt @"a" "hello" NMapEmpty)),+     (NMapExt @"b" "world" (NMapExt @"d" False NMapEmpty)))+    @?=+    (NMapExt @"a" "hello"+     (NMapExt @"b" "world"+      (NMapExt @"c" True+       (NMapExt @"d" False NMapEmpty))))+  , testCase "Product ununion . union == id" $+    ununionMap+    (unionMap+     ((NMapExt @"c" True (NMapExt @"a" "hello" NMapEmpty)),+      (NMapExt @"b" "world" (NMapExt @"d" False NMapEmpty))))+    @?=+    ((NMapExt @"c" True (NMapExt @"a" "hello" NMapEmpty)),+     (NMapExt @"b" "world" (NMapExt @"d" False NMapEmpty)))+  , testCase "Union of sums, 1st branch" $+    unionSum @_ @'["b" ':-> Bool] @'["a" ':-> Int]+    (Left (NSumThis @"b" True))+    @?=+    (NSumThat (NSumThis @"b" True))+  , testCase "Union of sums, 2nd branch" $+    unionSum @_ @'["b" ':-> Bool] @'["a" ':-> Int]+    (Right (NSumThis @"a" 1))+    @?=+    (NSumThis @"a" 1)+  , testCase "Sum ununion . union == id" $+    ununionSum @_ @'["b" ':-> Bool] @'["a" ':-> Int]+    (unionSum @_ @'["b" ':-> Bool] @'["a" ':-> Int]+     (Left (NSumThis @"b" True)))+    @?=+    (Left (NSumThis @"b" True))+  ]