packages feed

proton-0.0.1: src/Data/Profunctor/Coindexed.hs

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE DefaultSignatures #-}
module Data.Profunctor.Coindexed where

import Data.Profunctor
import Data.Void
import Control.Applicative
import Control.Monad
import Data.Tagged

class (Profunctor p, Profunctor q) => Coindexable e p q | q -> p where
    coindexed :: p a (Either e b) -> q a b
    default coindexed :: (e ~ Void, p ~ q) => p a (Either e b) -> q a b
    coindexed = rmap (either absurd id)

data Coindexed e p a b = Coindexed {runCoindexed :: (p a (Either e b))}

instance Profunctor p => Profunctor (Coindexed e p) where
  dimap f g (Coindexed p) = Coindexed (dimap f (right' g) p)

instance Choice p => Choice (Coindexed i p) where
  right' (Coindexed p) = Coindexed (dimap id reassoc $ right' p)
    where
      reassoc (Left c) = Right (Left c)
      reassoc (Right (Left i)) = Left i
      reassoc (Right (Right b)) = Right (Right b)

instance Profunctor p => Coindexable i p (Coindexed i p) where
  coindexed p = Coindexed p

instance Coindexable e (Forget r) (Forget r) where
  coindexed (Forget f) = (Forget f)

instance Coindexable Void (->) (->)

instance {-# OVERLAPPING #-} Functor f => Coindexable Void (Star f) (Star f) where
-- Could use selective applicative here instead.
instance (Alternative f, Monad f) => Coindexable e (Star f) (Star f) where
  coindexed (Star f) = Star $ f >=> either (const empty) pure
instance Functor f => Coindexable Void (Costar f) (Costar f) where
instance Coindexable Void Tagged Tagged where