module Data.Extensible.Sum (
(:|)(..)
, hoist
, embed
, (<:|)
, exhaust
, picked
) where
import Data.Extensible.Internal
import Data.Type.Equality
import Control.Applicative
import Data.Typeable
data (h :: k -> *) :| (s :: [k]) where
UnionAt :: Position xs x -> h x -> h :| xs
deriving instance Typeable (:|)
hoist :: (forall x. g x -> h x) -> g :| xs -> h :| xs
hoist f (UnionAt pos h) = UnionAt pos (f h)
embed :: (x ∈ xs) => h x -> h :| xs
embed = UnionAt membership
instance Show (h :| '[]) where
show = exhaust
instance (Show (h x), Show (h :| xs)) => Show (h :| (x ': xs)) where
showsPrec d = (\h -> showParen (d > 10) $ showString "inS " . showsPrec 11 h)
<:| showsPrec d
(<:|) :: (h x -> r) -> (h :| xs -> r) -> h :| (x ': xs) -> r
(<:|) r c = \(UnionAt pos h) -> case runPosition pos of
Left Refl -> r h
Right pos' -> c (UnionAt pos' h)
infixr 1 <:|
exhaust :: h :| '[] -> r
exhaust _ = error "Impossible"
picked :: forall f h x xs. (x ∈ xs, Applicative f) => (h x -> f (h x)) -> h :| xs -> f (h :| xs)
picked f u@(UnionAt pos h) = case comparePosition (membership :: Position xs x) pos of
Just Refl -> fmap (UnionAt pos) (f h)
Nothing -> pure u