module Generics.ApplyTwins (ApplyTwins (), apTwins) where
import GHC.Generics
apTwins :: ( Generic (m (x->y)), Generic (m x), Generic (m y)
, ApplyTwins (Rep (m (x->y))) (Rep (m x)) (Rep (m y))
)
=> m (x -> y) -> m x -> Maybe (m y)
apTwins a b = to <$> apt (from a) (from b)
class ApplyTwins mxy mx my where
apt :: mxy p -> mx p -> Maybe (my p)
instance ApplyTwins U1 U1 U1 where
apt U1 U1 = Just U1
instance ApplyTwins (K1 i x) (K1 i x) (K1 i x) where
apt (K1 x) (K1 _) = Just (K1 x)
instance
ApplyTwins (K1 i (x->y)) (K1 i x) (K1 i y) where
apt (K1 f) (K1 x) = Just (K1 (f x))
instance
( Generic fxy, Generic fx, Generic fy
, ApplyTwins (Rep fxy) (Rep fx) (Rep fy)
)
=> ApplyTwins (K1 i fxy) (K1 i fx) (K1 i fy) where
apt (K1 ff) (K1 fx) = K1 . to <$> apt (from ff) (from fx)
instance ApplyTwins fxy fx fy
=> ApplyTwins (M1 i c fxy) (M1 i c fx) (M1 i c fy) where
apt (M1 ff) (M1 fx) = M1 <$> apt ff fx
instance ApplyTwins fxy fx fy
=> ApplyTwins (Rec1 fxy) (Rec1 fx) (Rec1 fy) where
apt (Rec1 ff) (Rec1 fx) = Rec1 <$> apt ff fx
instance ( ApplyTwins fxy fx fy
, ApplyTwins gxy gx gy
)
=> ApplyTwins (fxy :+: gxy) (fx :+: gx) (fy :+: gy) where
apt (L1 ff) (L1 fx) = L1 <$> apt ff fx
apt (R1 gf) (R1 gx) = R1 <$> apt gf gx
apt _ _ = Nothing
instance ( ApplyTwins fxy fx fy
, ApplyTwins gxy gx gy
)
=> ApplyTwins (fxy :*: gxy) (fx :*: gx) (fy :*: gy) where
apt (ff :*: gf) (fx :*: gx) = (:*:) <$> apt ff fx <*> apt gf gx
instance ( Applicative f, Traversable f
, ApplyTwins gxy gx gy
)
=> ApplyTwins (f :.: gxy) (f :.: gx) (f :.: gy) where
apt (Comp1 fgf) (Comp1 fgx) = fmap Comp1. sequence $ apt <$> fgf <*> fgx