module Control.Category.Recursive where

import Control.Category (Category)
import qualified Data.Profunctor.Choice as P
import qualified Data.Profunctor.Strong as P

class Category k => Recursive k where
  recurseL :: (Either a s `k` Either b s) -> (a `k` b)
  recurseR :: (Either s a `k` Either s b) -> (a `k` b)

instance Recursive (->) where
  recurseL :: (Either a s -> Either b s) -> a -> b
recurseL = (Either a s -> Either b s) -> a -> b
forall (p :: * -> * -> *) a d b.
Cochoice p =>
p (Either a d) (Either b d) -> p a b
P.unleft
  recurseR :: (Either s a -> Either s b) -> a -> b
recurseR = (Either s a -> Either s b) -> a -> b
forall (p :: * -> * -> *) d a b.
Cochoice p =>
p (Either d a) (Either d b) -> p a b
P.unright

class Category k => Fixed k where
  fixL :: ((a, s) `k` (b, s)) -> (a `k` b)
  fixR :: ((s, a) `k` (s, b)) -> (a `k` b)

instance Fixed (->) where
  fixL :: ((a, s) -> (b, s)) -> a -> b
fixL = ((a, s) -> (b, s)) -> a -> b
forall (p :: * -> * -> *) a d b.
Costrong p =>
p (a, d) (b, d) -> p a b
P.unfirst
  fixR :: ((s, a) -> (s, b)) -> a -> b
fixR = ((s, a) -> (s, b)) -> a -> b
forall (p :: * -> * -> *) d a b.
Costrong p =>
p (d, a) (d, b) -> p a b
P.unsecond