{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE LiberalTypeSynonyms #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
module Generics.MultiRec.FoldAlg where
import Generics.MultiRec.Base
import Generics.MultiRec.HFunctor
type family Alg (f :: (* -> *) -> * -> *)
(r :: * -> *)
(ix :: *)
:: *
type instance Alg (K a) (r :: * -> *) ix = a -> r ix
type instance Alg (f :.: I xi) r ix = f (r xi) -> r ix
type instance Alg U (r :: * -> *) ix = r ix
type instance Alg (I xi) r ix = r xi -> r ix
type instance Alg (f :+: g) r ix = (Alg f r ix, Alg g r ix)
type instance Alg (f :*: g) r ix = Comp f r ix -> Alg g r ix
type instance Alg (f :>: xi) r ix = Alg f r xi
type instance Alg (C c f) r ix = Alg f r ix
type family Comp (f :: (* -> *) -> * -> *)
(r :: * -> *)
(ix :: *)
:: *
type instance Comp (I xi) r ix = r xi
type instance Comp (K a) r ix = a
type instance Comp (f :.: g) r ix = f (Comp g r ix)
type Algebra phi r = forall ix. phi ix -> Alg (PF phi) r ix
class Fold (f :: (* -> *) -> * -> *) where
alg :: Alg f r ix -> f r ix -> r ix
instance Fold (K a) where
alg f (K x) = f x
instance Fold U where
alg f U = f
instance Fold (I xi) where
alg f (I x) = f x
instance (Functor f) => Fold (f :.: I xi) where
alg f (D x) = f (fmap unI x)
instance (Fold f, Fold g) => Fold (f :+: g) where
alg (f, g) (L x) = alg f x
alg (f, g) (R x) = alg g x
instance (Fold g) => Fold (K a :*: g) where
alg f (K x :*: y) = alg (f x) y
instance (Fold g) => Fold (I xi :*: g) where
alg f (I x :*: y) = alg (f x) y
instance (Fold f) => Fold (f :>: xi) where
alg f (Tag x) = alg f x
instance (Fold f) => Fold (C c f) where
alg f (C x) = alg f x
fold :: forall phi ix r . (Fam phi, HFunctor phi (PF phi), Fold (PF phi)) =>
Algebra phi r -> phi ix -> ix -> r ix
fold f p = alg (f p) .
hmap (\ p (I0 x) -> fold f p x) p .
from p
infixr 5 &
(&) :: a -> b -> (a, b)
(&) = (,)