{-# LANGUAGE GADTs #-}
{-# LANGUAGE Arrows #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE ExistentialQuantification #-}
module Data.Profunctor.Arrow.Free where
import Control.Category hiding ((.), id)
import Data.Profunctor
import Data.Profunctor.Arrow
import Data.Profunctor.Traversing
import qualified Control.Category as C
import Prelude
data Free p a b where
Parr :: (a -> b) -> Free p a b
Free :: p x b -> Free p a x -> Free p a b
instance Profunctor p => Profunctor (Free p) where
dimap l r (Parr f) = Parr (dimap l r f)
dimap l r (Free f g) = Free (rmap r f) (lmap l g)
instance Profunctor p => Category (Free p) where
id = Parr id
Parr g . f = rmap g f
Free h g . f = Free h (g <<< f)
instance Strong p => Strong (Free p) where
first' (Parr f) = Parr (first' f)
first' (Free f g) = Free (first' f) (first' g)
instance Choice p => Choice (Free p) where
left' (Parr f) = Parr (left' f)
left' (Free f g) = Free (left' f) (left' g)
instance Closed p => Closed (Free p) where
closed (Parr f) = Parr (closed f)
closed (Free f g) = Free (closed f) (closed g)
instance Traversing p => Traversing (Free p) where
traverse' (Parr f) = Parr (traverse' f)
traverse' (Free f g) = Free (traverse' f) (traverse' g)
instance Mapping p => Mapping (Free p) where
map' (Parr f) = Parr (map' f)
map' (Free f g) = Free (map' f) (map' g)
foldFree :: Category q => Profunctor q => p :-> q -> Free p a b -> q a b
foldFree _ (Parr ab) = arr ab
foldFree pq (Free p f) = pq p <<< foldFree pq f
hoistFree :: p :-> q -> Free p a b -> Free q a b
hoistFree _ (Parr ab) = Parr ab
hoistFree pq (Free p f) = Free (pq p) (hoistFree pq f)
newtype Append r a b = Append { getAppend :: r }
instance Profunctor (Append r) where
dimap _ _ (Append x) = Append x
instance Monoid r => Category (Append r) where
id = Append mempty
Append x . Append y = Append (x <> y)