module HKT.Merge (Merge, merge) where import Protolude import HKT.Type (ID) import GHC.Generics (Generic, Rep, M1(M1), K1(K1), V1, U1, from, to, (:*:)((:*:))) import qualified Data.Maybe class Merge a where merge :: a ID -> a Maybe -> a ID default merge :: ( Generic (a Maybe) , Generic (a ID) , GMerge (Rep (a ID)) (Rep (a Maybe)) ) => a ID -> a Maybe -> a ID merge a b = to $ gmerge (from a ) (from b) class GMerge a b where gmerge :: a p -> b p -> a p instance GMerge a b => GMerge (M1 i c a) (M1 i c b) where gmerge (M1 a) (M1 b) = M1 $ gmerge a b {-# INLINE gmerge #-} instance (GMerge a b, GMerge c d) => GMerge (a :*: c) (b :*: d) where gmerge (a :*: c) (b :*: d) = gmerge a b :*: gmerge c d {-# INLINE gmerge #-} instance GMerge (K1 a k) (K1 a (Maybe k)) where gmerge (K1 a) (K1 ma) = K1 $ Data.Maybe.fromMaybe a ma {-# INLINE gmerge #-} instance GMerge U1 U1 where gmerge U1 _ = U1 {-# INLINE gmerge #-} instance GMerge V1 V1 where gmerge _ = (\case {}) {-# INLINE gmerge #-}