{-# LANGUAGE UndecidableInstances #-}
module Data.Barbie.Container
(
Container(..)
)
where
import Data.Barbie
import Data.Bifunctor (first)
import Data.Bitraversable (bitraverse)
import Data.Coerce (coerce)
import Data.Functor.Const
import Data.Functor.Prod (uncurryn)
import GHC.Generics (Generic)
newtype Container b a =
Container { getContainer :: b (Const a) }
deriving (Generic)
deriving instance Eq (b (Const a)) => Eq (Container b a)
deriving instance Ord (b (Const a)) => Ord (Container b a)
deriving instance Read (b (Const a)) => Read (Container b a)
deriving instance Show (b (Const a)) => Show (Container b a)
instance FunctorB b => Functor (Container b) where
fmap f =
Container . (bmap (first f)) . getContainer
instance TraversableB b => Foldable (Container b) where
foldMap f =
getConst . btraverse (coerce . first f) . getContainer
instance TraversableB b => Traversable (Container b) where
traverse f =
fmap Container . btraverse (bitraverse f pure) . getContainer
instance ProductB b => Applicative (Container b) where
pure a
= Container $ buniq (Const a)
l <*> r
= Container $ bmap (uncurryn appConst) (getContainer l /*/ getContainer r)
where
appConst :: Const (a -> a') x -> Const a x -> Const a' x
appConst (Const f) (Const a)
= Const (f a)