{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
module Control.Arrow.Square where
import Data.Square
import Data.Functor.Compose.List
import Data.Profunctor
import Data.Profunctor.Composition.List
import qualified Control.Arrow as A
arr :: A.Arrow a => Square '[] '[a] '[] '[]
arr = Square (P . A.arr . dimap unId Id . unHom)
(>>>) :: A.Arrow a => Square '[a, a] '[a] '[] '[]
(>>>) = Square (\(PComp p (P q)) -> P (A.arr Id A.<<< q A.<<< p A.<<< A.arr unId))
second :: A.Arrow a => Square '[a] '[a] '[(,) d] '[(,) d]
second = Square (P . (A.>>> A.arr F) . (A.<<< A.arr unF) . A.second . unP)
(***) :: A.Arrow a => Square21 '[a] '[a] '[a] (,) (,)
(***) = Square $ \(P p1 :**: P p2) -> P (A.arr UncurryF A.<<< p1 A.*** p2 A.<<< A.arr curryF)
right :: A.ArrowChoice a => Square '[a] '[a] '[Either d] '[Either d]
right = Square (P . (A.>>> A.arr F) . (A.<<< A.arr unF) . A.right . unP)
(+++) :: A.ArrowChoice a => Square21 '[a] '[a] '[a] Either Either
(+++) = Square $ \(P p1 :**: P p2) -> P (A.arr UncurryF A.<<< p1 A.+++ p2 A.<<< A.arr curryF)