barbies-layered-0.1.0.0: src/Data/Functor/Barbie/Layered.hs
{-# LANGUAGE RankNTypes #-}
module Data.Functor.Barbie.Layered
( FunctorB (..)
) where
import Barbies (Unit (Unit), Void)
import Data.Data (Proxy (Proxy))
import Data.Functor.Compose (Compose (Compose))
import Data.Functor.Const (Const (Const))
import Data.Functor.Constant (Constant (Constant))
import Data.Functor.Product (Product (Pair))
import Data.Functor.Sum (Sum (InL, InR))
-- | Barbie-types that can be mapped over. Instances of 'FunctorB' should
-- satisfy the following laws:
--
-- @
-- 'bmap' 'id' = 'id'
-- 'bmap' f . 'bmap' g = 'bmap' (f . g)
-- @
class FunctorB b where
bmap :: forall f g. (Functor f, Functor g) => (forall a. f a -> g a) -> b f -> b g
instance FunctorB Proxy where
bmap _ _ = Proxy
instance FunctorB Void where
bmap _ _ = undefined
instance FunctorB Unit where
bmap _ _ = Unit
instance FunctorB (Constant a) where
bmap _ (Constant a) = Constant a
instance FunctorB (Const a) where
bmap _ (Const a) = Const a
instance (FunctorB a, FunctorB b) => FunctorB (Product a b) where
bmap f (Pair x y) = Pair (bmap f x) (bmap f y)
instance (FunctorB a, FunctorB b) => FunctorB (Sum a b) where
bmap f (InL x) = InL (bmap f x)
bmap f (InR x) = InR (bmap f x)
instance (Functor f, FunctorB b) => FunctorB (Compose f b) where
bmap h (Compose x) = Compose (bmap h <$> x)