{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
module Data.Profunctor.Composition.List where
import Data.Profunctor
import Data.Profunctor.Composition
import Data.Type.List
data PList (ps :: [* -> * -> *]) (a :: *) (b :: *) where
Hom :: { unHom :: a -> b } -> PList '[] a b
P :: { unP :: p a b } -> PList '[p] a b
PComp :: p a x -> PList (q ': qs) x b -> PList (p ': q ': qs) a b
instance Profunctor (PList '[]) where
dimap l r (Hom f) = Hom (r . f . l)
instance Profunctor p => Profunctor (PList '[p]) where
dimap l r (P p) = P (dimap l r p)
instance (Profunctor p, Profunctor (PList (q ': qs))) => Profunctor (PList (p ': q ': qs)) where
dimap l r (PComp p ps) = PComp (lmap l p) (rmap r ps)
class PAppend p where
pappend :: Profunctor (PList q) => Procompose (PList q) (PList p) a b -> PList (p ++ q) a b
punappend :: PList (p ++ q) a b -> Procompose (PList q) (PList p) a b
instance PAppend '[] where
pappend (Procompose q (Hom f)) = lmap f q
punappend q = Procompose q (Hom id)
instance Profunctor p => PAppend '[p] where
pappend (Procompose (Hom f) (P p)) = P (rmap f p)
pappend (Procompose q@P{} (P p)) = PComp p q
pappend (Procompose q@PComp{} (P p)) = PComp p q
punappend p@P{} = Procompose (Hom id) p
punappend (PComp p qs) = Procompose qs (P p)
instance (Profunctor p, PAppend (q ': qs)) => PAppend (p ': q ': qs) where
pappend (Procompose q (PComp p ps)) = PComp p (pappend (Procompose q ps))
punappend (PComp p pq) = case punappend pq of Procompose q ps -> Procompose q (PComp p ps)