{-# LANGUAGE UndecidableSuperClasses, UndecidableInstances, FlexibleInstances, TemplateHaskell #-}
module AST.Combinator.Compose
( Compose(..), _Compose
) where
import AST.Class.Apply
import AST.Class.Foldable
import AST.Class.Functor
import AST.Class.Nodes
import AST.Class.Pointed
import AST.Class.Traversable
import AST.Class.ZipMatch (ZipMatch(..))
import AST.Knot
import AST.TH.Internal.Instances (makeCommonInstances)
import qualified Control.Lens as Lens
import Control.Lens.Operators
import Data.Functor.Product.PolyKinds (Product(..))
import Data.Proxy (Proxy(..))
import GHC.Generics (Generic)
import Prelude.Compat
newtype Compose a b k = MkCompose { getCompose :: Tree a (Compose b (GetKnot k)) }
deriving stock Generic
makeCommonInstances [''Compose]
{-# INLINE _Compose #-}
_Compose ::
Lens.Iso
(Tree (Compose a0 b0) k0) (Tree (Compose a1 b1) k1)
(Tree a0 (Compose b0 k0)) (Tree a1 (Compose b1 k1))
_Compose = Lens.iso getCompose MkCompose
instance (KNodes a, KNodes b) => KNodes (Compose a b) where
type KNodesConstraint (Compose a b) c = KNodesConstraint a (ComposeConstraint0 c b)
data KWitness (Compose a b) n where
KWitness_Compose :: KWitness a a0 -> KWitness b b0 -> KWitness (Compose a b) (Compose a0 b0)
{-# INLINE kLiftConstraint #-}
kLiftConstraint (KWitness_Compose w0 w1) p r =
kLiftConstraint w0 (p0 p) (kLiftConstraint w1 (p1 p w0) r)
where
p0 :: Proxy c -> Proxy (ComposeConstraint0 c b)
p0 _ = Proxy
p1 :: Proxy c -> KWitness a a0 -> Proxy (ComposeConstraint1 c a0)
p1 _ _ = Proxy
class KNodesConstraint b (ComposeConstraint1 c k0) => ComposeConstraint0 c b k0
instance KNodesConstraint b (ComposeConstraint1 c k0) => ComposeConstraint0 c b k0
class c (Compose k0 k1) => ComposeConstraint1 c k0 k1
instance c (Compose k0 k1) => ComposeConstraint1 c k0 k1
instance
(KNodes a, KPointed a, KPointed b) =>
KPointed (Compose a b) where
{-# INLINE pureK #-}
pureK x =
_Compose #
pureK
( \wa ->
_Compose # pureK (\wb -> _Compose # x (KWitness_Compose wa wb))
)
instance (KFunctor a, KFunctor b) => KFunctor (Compose a b) where
{-# INLINE mapK #-}
mapK f =
_Compose %~
mapK
( \w0 ->
_Compose %~ mapK (\w1 -> _Compose %~ f (KWitness_Compose w0 w1))
)
instance (KApply a, KApply b) => KApply (Compose a b) where
{-# INLINE zipK #-}
zipK (MkCompose a0) =
_Compose %~
mapK
( \_ (Pair (MkCompose b0) (MkCompose b1)) ->
_Compose #
mapK
( \_ (Pair (MkCompose i0) (MkCompose i1)) ->
_Compose # Pair i0 i1
) (zipK b0 b1)
)
. zipK a0
instance (KFoldable a, KFoldable b) => KFoldable (Compose a b) where
{-# INLINE foldMapK #-}
foldMapK f =
foldMapK
( \w0 ->
foldMapK (\w1 -> f (KWitness_Compose w0 w1) . (^. _Compose)) . (^. _Compose)
) . (^. _Compose)
instance (KTraversable a, KTraversable b) => KTraversable (Compose a b) where
{-# INLINE sequenceK #-}
sequenceK =
_Compose
( sequenceK .
mapK (const (MkContainedK . _Compose (traverseK (const (_Compose runContainedK)))))
)
instance
(ZipMatch k0, ZipMatch k1, KTraversable k0, KFunctor k1) =>
ZipMatch (Compose k0 k1) where
{-# INLINE zipMatch #-}
zipMatch (MkCompose x) (MkCompose y) =
zipMatch x y
>>= traverseK
(\_ (Pair (MkCompose cx) (MkCompose cy)) ->
zipMatch cx cy
<&> mapK
(\_ (Pair (MkCompose bx) (MkCompose by)) -> Pair bx by & MkCompose)
<&> (_Compose #)
)
<&> (_Compose #)