{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
module Control.Arrow.Square where
import Data.Square
import Data.Profunctor
import Data.Profunctor.Composition
import Data.Profunctor.Composition.List
import qualified Control.Arrow as A
arr :: (A.Arrow a, Profunctor a) => Square '[] '[a] '[] '[]
arr = mkSquare A.arr
(>>>) :: (A.Arrow a, Profunctor a) => Square '[a, a] '[a] '[] '[]
(>>>) = mkSquare (\(Procompose q p) -> p A.>>> q)
second :: (A.Arrow a, Profunctor a) => Square '[a] '[a] '[(,) d] '[(,) d]
second = mkSquare A.second
(***) :: 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, Profunctor a) => Square '[a] '[a] '[Either d] '[Either d]
right = mkSquare A.right
(+++) :: 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)