{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Generics.MRSOP.Base.Combinators where
import Data.Function (on)
import Control.Applicative
import Control.Monad
import Control.Monad.Identity
import Generics.MRSOP.Base.NS
import Generics.MRSOP.Base.NP
import Generics.MRSOP.Base.Universe
import Generics.MRSOP.Base.Class
import Generics.MRSOP.Util
geq :: forall ki fam codes ix
. (Family ki fam codes)
=> (forall k . ki k -> ki k -> Bool)
-> El fam ix -> El fam ix -> Bool
geq kp = eqFix kp `on` dfrom
composM :: forall ki fam codes ix m
. (Monad m , Family ki fam codes, IsNat ix)
=> (forall iy . IsNat iy => SNat iy -> El fam iy -> m (El fam iy))
-> El fam ix -> m (El fam ix)
composM f = (sto @fam <$>)
. mapRepM (\x -> f (getElSNat x) x)
. sfrom @fam
compos :: forall ki fam codes ix
. (Family ki fam codes, IsNat ix)
=> (forall iy . IsNat iy => SNat iy -> El fam iy -> El fam iy)
-> El fam ix -> El fam ix
compos f = runIdentity . composM (\iy -> return . f iy)
crushM :: forall ki fam codes ix r m
. (Monad m , Family ki fam codes)
=> (forall k. ki k -> m r) -> ([r] -> m r)
-> El fam ix -> m r
crushM kstep combine
= elimRep kstep (crushM kstep combine) (combine <.> sequence) . sfrom
crush :: forall ki fam codes ix r
. (Family ki fam codes)
=> (forall k. ki k -> r) -> ([r] -> r)
-> El fam ix -> r
crush kstep combine = runIdentity . crushM (return . kstep) (return . combine)