{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
module Barbies.Generics.Applicative
( GApplicative(..)
)
where
import Data.Functor.Product(Product(..))
import Data.Proxy(Proxy (..))
import Data.Generics.GenericN
class GApplicative n (f :: k -> *) (g :: k -> *) repbf repbg repbfg where
gprod
:: Proxy n
-> Proxy f
-> Proxy g
-> repbf x
-> repbg x
-> repbfg x
gpure
:: (f ~ g, repbf ~ repbg)
=> Proxy n
-> Proxy f
-> Proxy repbf
-> Proxy repbfg
-> (forall a . f a)
-> repbf x
instance
( GApplicative n f g repf repg repfg
) => GApplicative n f g (M1 i c repf)
(M1 i c repg)
(M1 i c repfg)
where
gprod pn pf pg (M1 l) (M1 r)
= M1 (gprod pn pf pg l r)
{-# INLINE gprod #-}
gpure pn pf _ _ x
= M1 (gpure pn pf (Proxy @repf) (Proxy @repfg) x)
{-# INLINE gpure #-}
instance GApplicative n f g U1 U1 U1 where
gprod _ _ _ U1 U1 = U1
{-# INLINE gprod #-}
gpure _ _ _ _ _ = U1
{-# INLINE gpure #-}
instance
( GApplicative n f g lf lg lfg
, GApplicative n f g rf rg rfg
) => GApplicative n f g (lf :*: rf)
(lg :*: rg)
(lfg :*: rfg) where
gprod pn pf pg (l1 :*: l2) (r1 :*: r2)
= (l1 `lprod` r1) :*: (l2 `rprod` r2)
where
lprod = gprod pn pf pg
rprod = gprod pn pf pg
{-# INLINE gprod #-}
gpure pn pf _ _ x
= gpure pn pf (Proxy @lf) (Proxy @lfg) x
:*: gpure pn pf (Proxy @rf) (Proxy @rfg) x
{-# INLINE gpure #-}
type P = Param
instance
GApplicative n f g (Rec (P n f a) (f a))
(Rec (P n g a) (g a))
(Rec (P n (f `Product` g) a) ((f `Product` g) a))
where
gpure _ _ _ _ x
= Rec (K1 x)
{-# INLINE gpure #-}
gprod _ _ _ (Rec (K1 fa)) (Rec (K1 ga))
= Rec (K1 (Pair fa ga))
{-# INLINE gprod #-}
instance
( Applicative h
) =>
GApplicative n f g (Rec (h (P n f a)) (h (f a)))
(Rec (h (P n g a)) (h (g a)))
(Rec (h (P n (f `Product` g) a)) (h ((f `Product` g) a)))
where
gpure _ _ _ _ x
= Rec (K1 $ pure x)
{-# INLINE gpure #-}
gprod _ _ _ (Rec (K1 fa)) (Rec (K1 ga))
= Rec (K1 (Pair <$> fa <*> ga))
{-# INLINE gprod #-}
instance
( Monoid x
) => GApplicative n f g (Rec x x) (Rec x x) (Rec x x)
where
gpure _ _ _ _ _
= Rec (K1 mempty)
{-# INLINE gpure #-}
gprod _ _ _ (Rec (K1 l)) (Rec (K1 r))
= Rec (K1 (l <> r))
{-# INLINE gprod #-}