module Data.Type.Sum where
import Data.Type.Index
import Type.Class.Higher
import Type.Class.Witness
import Type.Family.List
data Sum (f :: k -> *) :: [k] -> * where
InL :: !(f a) -> Sum f (a :< as)
InR :: !(Sum f as) -> Sum f (a :< as)
deriving instance ListC (Eq <$> f <$> as) => Eq (Sum f as)
deriving instance
( ListC (Eq <$> f <$> as)
, ListC (Ord <$> f <$> as)
) => Ord (Sum f as)
deriving instance ListC (Show <$> f <$> as) => Show (Sum f as)
instance Eq1 f => Eq1 (Sum f) where
eq1 = \case
InL a -> \case
InL b -> a =#= b
_ -> False
InR a -> \case
InR b -> a =#= b
_ -> False
instance Ord1 f => Ord1 (Sum f) where
compare1 = \case
InL a -> \case
InL b -> compare1 a b
_ -> LT
InR a -> \case
InR b -> compare1 a b
_ -> GT
instance Show1 f => Show1 (Sum f) where
showsPrec1 d = showParen (d > 10) . \case
InL a -> showString "InL "
. showsPrec1 11 a
InR b -> showString "InR "
. showsPrec1 11 b
instance Read1 f => Read1 (Sum f) where
readsPrec1 d = readParen (d > 10) $ \s0 ->
[ (a >>- Some . InL,s2)
| ("InL",s1) <- lex s0
, (a,s2) <- readsPrec1 11 s1
] ++
[ (a >>- Some . InR,s2)
| ("InR",s1) <- lex s0
, (a,s2) <- readsPrec1 11 s1
]
nilSum :: Sum f Ø -> Void
nilSum = impossible
decomp :: Sum f (a :< as) -> Either (f a) (Sum f as)
decomp = \case
InL a -> Left a
InR s -> Right s
injectSum :: Index as a -> f a -> Sum f as
injectSum = \case
IZ -> InL
IS x -> InR . injectSum x
inj :: (a ∈ as) => f a -> Sum f as
inj = injectSum elemIndex
prj :: (a ∈ as) => Sum f as -> Maybe (f a)
prj = index elemIndex
index :: Index as a -> Sum f as -> Maybe (f a)
index = \case
IZ -> \case
InL a -> Just a
_ -> Nothing
IS x -> \case
InR s -> index x s
_ -> Nothing
elimSum :: (forall x xs. f x -> p (x :< xs))
-> (forall x xs. Index as x -> p xs -> p (x :< xs))
-> Sum f as
-> p as
elimSum t n = \case
InL a -> t a
InR s -> n IZ $ elimSum t (n . IS) s
instance Functor1 Sum where
map1 f = \case
InL a -> InL $ f a
InR s -> InR $ map1 f s
instance IxFunctor1 Index Sum where
imap1 f = \case
InL a -> InL $ f IZ a
InR s -> InR $ imap1 (f . IS) s
instance Foldable1 Sum where
foldMap1 f = \case
InL a -> f a
InR s -> foldMap1 f s
instance IxFoldable1 Index Sum where
ifoldMap1 f = \case
InL a -> f IZ a
InR s -> ifoldMap1 (f . IS) s
instance Traversable1 Sum where
traverse1 f = \case
InL a -> InL <$> f a
InR s -> InR <$> traverse1 f s
instance IxTraversable1 Index Sum where
itraverse1 f = \case
InL a -> InL <$> f IZ a
InR s -> InR <$> itraverse1 (f . IS) s
instance Witness p q (f a) => Witness p q (Sum f '[a]) where
type WitnessC p q (Sum f '[a]) = Witness p q (f a)
(\\) r = \case
InL a -> r \\ a
_ -> error "impossible type"
instance (Witness p q (f a), Witness p q (Sum f (b :< as))) => Witness p q (Sum f (a :< b :< as)) where
type WitnessC p q (Sum f (a :< b :< as)) = (Witness p q (f a), Witness p q (Sum f (b :< as)))
(\\) r = \case
InL a -> r \\ a
InR s -> r \\ s