{-# LANGUAGE UndecidableInstances #-}
module Generic.Type.Function.FoldMap where
import DeFun.Core ( type (~>), type (@@) )
import Data.Kind ( type Type )
import GHC.Generics
-- | 'foldMap' on generic type representations (field product level).
--
-- Will work for single-constructor types as well thanks to meta unwrapping.
type GTFoldMapC
:: (m ~> m ~> m) -- | type-level 'mappend' defun symbol
-> m -- | type-level 'mempty'
-> (Type ~> m) -- | base case defun symbol
-> (k -> Type) -- | generic representation (field product level)
-> m
type family GTFoldMapC tmappend tmempty f gf where
GTFoldMapC tmappend tmempty f U1 = tmempty
GTFoldMapC tmappend tmempty f (K1 i c) = f @@ c
GTFoldMapC tmappend tmempty f (l :*: r) = tmappend
@@ GTFoldMapC tmappend tmempty f l
@@ GTFoldMapC tmappend tmempty f r
GTFoldMapC tmappend tmempty f (M1 _ _ gf) = GTFoldMapC tmappend tmempty f gf