module Data.Functor.Invariant.Day.Chain (
DayChain(.., Gather, Knot)
, runCoDayChain
, runContraDayChain
, chainAp
, chainDiv
, gather, gathered
, assembleDayChain
, assembleDayChainRec
, concatDayChain
, concatDayChainRec
, DayChain1(.., DayChain1)
, runCoDayChain1
, runContraDayChain1
, chainAp1
, chainDiv1
, gather1, gathered1
, assembleDayChain1
, assembleDayChain1Rec
, concatDayChain1
, concatDayChain1Rec
, runDayApply
, runDayDivise
) where
import Control.Applicative
import Control.Applicative.Free (Ap(..))
import Control.Applicative.ListF (MaybeF(..))
import Control.Natural
import Data.Coerce
import Data.Functor.Apply
import Data.Functor.Apply.Free (Ap1(..))
import Data.Functor.Contravariant.Divise
import Data.Functor.Contravariant.Divisible
import Data.Functor.Contravariant.Divisible.Free (Div(..), Div1)
import Data.Functor.Identity
import Data.Functor.Invariant
import Data.Functor.Invariant.Day
import Data.HBifunctor.Tensor hiding (elim1, elim2, intro1, intro2)
import Data.HFunctor
import Data.HFunctor.Chain
import Data.HFunctor.Chain.Internal
import Data.SOP hiding (hmap)
import qualified Data.Vinyl as V
import qualified Data.Vinyl.Functor as V
runDayApply
:: forall f g h. Apply h
=> f ~> h
-> g ~> h
-> Day f g ~> h
runDayApply f g (Day x y j _) = liftF2 j (f x) (g y)
runDayDivise
:: forall f g h. Divise h
=> f ~> h
-> g ~> h
-> Day f g ~> h
runDayDivise f g (Day x y _ h) = divise h (f x) (g y)
runCoDayChain1
:: forall f g. Apply g
=> f ~> g
-> DayChain1 f ~> g
runCoDayChain1 f = foldChain1 f (runDayApply f id) . unDayChain1
runContraDayChain1
:: forall f g. Divise g
=> f ~> g
-> DayChain1 f ~> g
runContraDayChain1 f = foldChain1 f (runDayDivise f id) . unDayChain1
runCoDayChain
:: forall f g. Applicative g
=> f ~> g
-> DayChain f ~> g
runCoDayChain f = foldChain (pure . runIdentity) (\case Day x y h _ -> liftA2 h (f x) y)
. unDayChain
runContraDayChain
:: forall f g. Divisible g
=> f ~> g
-> DayChain f ~> g
runContraDayChain f = foldChain (const conquer) (\case Day x y _ g -> divide g (f x) y)
. unDayChain
chainAp :: DayChain f ~> Ap f
chainAp = runCoDayChain inject
chainAp1 :: DayChain1 f ~> Ap1 f
chainAp1 = runCoDayChain1 inject
chainDiv :: DayChain f ~> Div f
chainDiv = runContraDayChain inject
chainDiv1 :: DayChain1 f ~> Div1 f
chainDiv1 = runContraDayChain1 inject
pattern Gather :: (a -> (b, c)) -> (b -> c -> a) -> f b -> DayChain f c -> DayChain f a
pattern Gather f g x xs <- (unGather_->MaybeF (Just (Day x xs g f)))
where
Gather f g x xs = DayChain $ More $ Day x (unDayChain xs) g f
unGather_ :: DayChain f ~> MaybeF (Day f (DayChain f))
unGather_ = \case
DayChain (More (Day x xs g f)) -> MaybeF . Just $ Day x (DayChain xs) g f
DayChain (Done _ ) -> MaybeF Nothing
pattern Knot :: a -> DayChain f a
pattern Knot x = DayChain (Done (Identity x))
{-# COMPLETE Gather, Knot #-}
pattern DayChain1 :: Invariant f => (a -> (b, c)) -> (b -> c -> a) -> f b -> DayChain f c -> DayChain1 f a
pattern DayChain1 f g x xs <- (coerce splitChain1->Day x xs g f)
where
DayChain1 f g x xs = unsplitNE $ Day x xs g f
{-# COMPLETE DayChain1 #-}
gather
:: (a -> (b, c))
-> (b -> c -> a)
-> DayChain f b
-> DayChain f c
-> DayChain f a
gather f g x y = coerce appendChain (Day x y g f)
gathered
:: DayChain f a
-> DayChain f b
-> DayChain f (a, b)
gathered = gather id (,)
gather1
:: Invariant f
=> (a -> (b, c))
-> (b -> c -> a)
-> DayChain1 f b
-> DayChain1 f c
-> DayChain1 f a
gather1 f g x y = coerce appendChain1 (Day x y g f)
gathered1
:: Invariant f
=> DayChain1 f a
-> DayChain1 f b
-> DayChain1 f (a, b)
gathered1 = gather1 id (,)
assembleDayChain
:: NP f as
-> DayChain f (NP I as)
assembleDayChain = \case
Nil -> DayChain $ Done $ Identity Nil
x :* xs -> DayChain $ More $ Day
x
(unDayChain (assembleDayChain xs))
consNPI
unconsNPI
concatDayChain
:: NP (DayChain f) as
-> DayChain f (NP I as)
concatDayChain = \case
Nil -> DayChain $ Done $ Identity Nil
x :* xs -> coerce appendChain $ Day
x
(concatDayChain xs)
consNPI
unconsNPI
assembleDayChain1
:: Invariant f
=> NP f (a ': as)
-> DayChain1 f (NP I (a ': as))
assembleDayChain1 = \case
x :* xs -> DayChain1_ $ case xs of
Nil -> Done1 $ invmap ((:* Nil) . I) (unI . hd) x
_ :* _ -> More1 $ Day
x
(unDayChain1 (assembleDayChain1 xs))
consNPI
unconsNPI
concatDayChain1
:: Invariant f
=> NP (DayChain1 f) (a ': as)
-> DayChain1 f (NP I (a ': as))
concatDayChain1 = \case
x :* xs -> case xs of
Nil -> invmap ((:* Nil) . I) (unI . hd) x
_ :* _ -> coerce appendChain1 $ Day
x
(concatDayChain1 xs)
consNPI
unconsNPI
unconsNPI :: NP I (a ': as) -> (a, NP I as)
unconsNPI (I y :* ys) = (y, ys)
consNPI :: a -> NP I as -> NP I (a ': as)
consNPI y ys = I y :* ys
assembleDayChainRec
:: V.Rec f as
-> DayChain f (V.XRec V.Identity as)
assembleDayChainRec = \case
V.RNil -> DayChain $ Done $ Identity V.RNil
x V.:& xs -> DayChain $ More $ Day
x
(unDayChain (assembleDayChainRec xs))
(V.::&)
unconsRec
concatDayChainRec
:: V.Rec (DayChain f) as
-> DayChain f (V.XRec V.Identity as)
concatDayChainRec = \case
V.RNil -> DayChain $ Done $ Identity V.RNil
x V.:& xs -> coerce appendChain $ Day
x
(concatDayChainRec xs)
(V.::&)
unconsRec
assembleDayChain1Rec
:: Invariant f
=> V.Rec f (a ': as)
-> DayChain1 f (V.XRec V.Identity (a ': as))
assembleDayChain1Rec = \case
x V.:& xs -> case xs of
V.RNil -> DayChain1_ $ Done1 $ invmap (V.::& V.RNil) (\case z V.::& _ -> z) x
_ V.:& _ -> DayChain1_ $ More1 $ Day
x
(unDayChain1 (assembleDayChain1Rec xs))
(V.::&)
unconsRec
concatDayChain1Rec
:: Invariant f
=> V.Rec (DayChain1 f) (a ': as)
-> DayChain1 f (V.XRec V.Identity (a ': as))
concatDayChain1Rec = \case
x V.:& xs -> case xs of
V.RNil -> invmap (V.::& V.RNil) (\case z V.::& _ -> z) x
_ V.:& _ -> coerce appendChain1 $ Day
x
(concatDayChain1Rec xs)
(V.::&)
unconsRec
unconsRec :: V.XRec V.Identity (a ': as) -> (a, V.XRec V.Identity as)
unconsRec (y V.::& ys) = (y, ys)