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

import Data.Profunctor
import Data.Profunctor.Traversing
import Data.Tagged

class (Profunctor p, Profunctor q) => Indexable i p q | p -> q where
    indexed :: p a b -> q (i, a) b
    default indexed :: (p ~ q) => p a b -> q (i, a) b
    indexed = ((i, a) -> a) -> q a b -> q (i, a) b
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap (i, a) -> a
forall a b. (a, b) -> b
snd

-- closeIndex :: (Closed q, Indexable i p q) => p a b -> q a (i -> b)
-- closeIndex = lmap (flip (,)) . closed  . indexed

data Indexed i p a b = Indexed (p (i, a) b)
newtype UnIndexed i p a b = UnIndexed (p a b)
  deriving newtype (q b c -> UnIndexed i p a b -> UnIndexed i p a c
UnIndexed i p b c -> q a b -> UnIndexed i p a c
(a -> b) -> (c -> d) -> UnIndexed i p b c -> UnIndexed i p a d
(a -> b) -> UnIndexed i p b c -> UnIndexed i p a c
(b -> c) -> UnIndexed i p a b -> UnIndexed i p a c
(forall a b c d.
 (a -> b) -> (c -> d) -> UnIndexed i p b c -> UnIndexed i p a d)
-> (forall a b c.
    (a -> b) -> UnIndexed i p b c -> UnIndexed i p a c)
-> (forall b c a.
    (b -> c) -> UnIndexed i p a b -> UnIndexed i p a c)
-> (forall a b c (q :: * -> * -> *).
    Coercible c b =>
    q b c -> UnIndexed i p a b -> UnIndexed i p a c)
-> (forall a b c (q :: * -> * -> *).
    Coercible b a =>
    UnIndexed i p b c -> q a b -> UnIndexed i p a c)
-> Profunctor (UnIndexed i p)
forall a b c. (a -> b) -> UnIndexed i p b c -> UnIndexed i p a c
forall b c a. (b -> c) -> UnIndexed i p a b -> UnIndexed i p a c
forall a b c d.
(a -> b) -> (c -> d) -> UnIndexed i p b c -> UnIndexed i p a d
forall a b c (q :: * -> * -> *).
Coercible b a =>
UnIndexed i p b c -> q a b -> UnIndexed i p a c
forall a b c (q :: * -> * -> *).
Coercible c b =>
q b c -> UnIndexed i p a b -> UnIndexed i p a c
forall i (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> UnIndexed i p b c -> UnIndexed i p a c
forall i (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> UnIndexed i p a b -> UnIndexed i p a c
forall i (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> UnIndexed i p b c -> UnIndexed i p a d
forall i (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
UnIndexed i p b c -> q a b -> UnIndexed i p a c
forall i (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> UnIndexed i p a b -> UnIndexed i p a c
forall (p :: * -> * -> *).
(forall a b c d. (a -> b) -> (c -> d) -> p b c -> p a d)
-> (forall a b c. (a -> b) -> p b c -> p a c)
-> (forall b c a. (b -> c) -> p a b -> p a c)
-> (forall a b c (q :: * -> * -> *).
    Coercible c b =>
    q b c -> p a b -> p a c)
-> (forall a b c (q :: * -> * -> *).
    Coercible b a =>
    p b c -> q a b -> p a c)
-> Profunctor p
.# :: UnIndexed i p b c -> q a b -> UnIndexed i p a c
$c.# :: forall i (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible b a) =>
UnIndexed i p b c -> q a b -> UnIndexed i p a c
#. :: q b c -> UnIndexed i p a b -> UnIndexed i p a c
$c#. :: forall i (p :: * -> * -> *) a b c (q :: * -> * -> *).
(Profunctor p, Coercible c b) =>
q b c -> UnIndexed i p a b -> UnIndexed i p a c
rmap :: (b -> c) -> UnIndexed i p a b -> UnIndexed i p a c
$crmap :: forall i (p :: * -> * -> *) b c a.
Profunctor p =>
(b -> c) -> UnIndexed i p a b -> UnIndexed i p a c
lmap :: (a -> b) -> UnIndexed i p b c -> UnIndexed i p a c
$clmap :: forall i (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> UnIndexed i p b c -> UnIndexed i p a c
dimap :: (a -> b) -> (c -> d) -> UnIndexed i p b c -> UnIndexed i p a d
$cdimap :: forall i (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> UnIndexed i p b c -> UnIndexed i p a d
Profunctor, Profunctor (UnIndexed i p)
Profunctor (UnIndexed i p) =>
(forall a b x.
 UnIndexed i p a b -> UnIndexed i p (x -> a) (x -> b))
-> Closed (UnIndexed i p)
UnIndexed i p a b -> UnIndexed i p (x -> a) (x -> b)
forall a b x. UnIndexed i p a b -> UnIndexed i p (x -> a) (x -> b)
forall i (p :: * -> * -> *). Closed p => Profunctor (UnIndexed i p)
forall i (p :: * -> * -> *) a b x.
Closed p =>
UnIndexed i p a b -> UnIndexed i p (x -> a) (x -> b)
forall (p :: * -> * -> *).
Profunctor p =>
(forall a b x. p a b -> p (x -> a) (x -> b)) -> Closed p
closed :: UnIndexed i p a b -> UnIndexed i p (x -> a) (x -> b)
$cclosed :: forall i (p :: * -> * -> *) a b x.
Closed p =>
UnIndexed i p a b -> UnIndexed i p (x -> a) (x -> b)
$cp1Closed :: forall i (p :: * -> * -> *). Closed p => Profunctor (UnIndexed i p)
Closed, Profunctor (UnIndexed i p)
Profunctor (UnIndexed i p) =>
(forall a b c. UnIndexed i p a b -> UnIndexed i p (a, c) (b, c))
-> (forall a b c. UnIndexed i p a b -> UnIndexed i p (c, a) (c, b))
-> Strong (UnIndexed i p)
UnIndexed i p a b -> UnIndexed i p (a, c) (b, c)
UnIndexed i p a b -> UnIndexed i p (c, a) (c, b)
forall a b c. UnIndexed i p a b -> UnIndexed i p (a, c) (b, c)
forall a b c. UnIndexed i p a b -> UnIndexed i p (c, a) (c, b)
forall i (p :: * -> * -> *). Strong p => Profunctor (UnIndexed i p)
forall i (p :: * -> * -> *) a b c.
Strong p =>
UnIndexed i p a b -> UnIndexed i p (a, c) (b, c)
forall i (p :: * -> * -> *) a b c.
Strong p =>
UnIndexed i p a b -> UnIndexed i p (c, a) (c, b)
forall (p :: * -> * -> *).
Profunctor p =>
(forall a b c. p a b -> p (a, c) (b, c))
-> (forall a b c. p a b -> p (c, a) (c, b)) -> Strong p
second' :: UnIndexed i p a b -> UnIndexed i p (c, a) (c, b)
$csecond' :: forall i (p :: * -> * -> *) a b c.
Strong p =>
UnIndexed i p a b -> UnIndexed i p (c, a) (c, b)
first' :: UnIndexed i p a b -> UnIndexed i p (a, c) (b, c)
$cfirst' :: forall i (p :: * -> * -> *) a b c.
Strong p =>
UnIndexed i p a b -> UnIndexed i p (a, c) (b, c)
$cp1Strong :: forall i (p :: * -> * -> *). Strong p => Profunctor (UnIndexed i p)
Strong, Profunctor (UnIndexed i p)
Profunctor (UnIndexed i p) =>
(forall a b c.
 UnIndexed i p a b -> UnIndexed i p (Either a c) (Either b c))
-> (forall a b c.
    UnIndexed i p a b -> UnIndexed i p (Either c a) (Either c b))
-> Choice (UnIndexed i p)
UnIndexed i p a b -> UnIndexed i p (Either a c) (Either b c)
UnIndexed i p a b -> UnIndexed i p (Either c a) (Either c b)
forall a b c.
UnIndexed i p a b -> UnIndexed i p (Either a c) (Either b c)
forall a b c.
UnIndexed i p a b -> UnIndexed i p (Either c a) (Either c b)
forall i (p :: * -> * -> *). Choice p => Profunctor (UnIndexed i p)
forall i (p :: * -> * -> *) a b c.
Choice p =>
UnIndexed i p a b -> UnIndexed i p (Either a c) (Either b c)
forall i (p :: * -> * -> *) a b c.
Choice p =>
UnIndexed i p a b -> UnIndexed i p (Either c a) (Either c b)
forall (p :: * -> * -> *).
Profunctor p =>
(forall a b c. p a b -> p (Either a c) (Either b c))
-> (forall a b c. p a b -> p (Either c a) (Either c b)) -> Choice p
right' :: UnIndexed i p a b -> UnIndexed i p (Either c a) (Either c b)
$cright' :: forall i (p :: * -> * -> *) a b c.
Choice p =>
UnIndexed i p a b -> UnIndexed i p (Either c a) (Either c b)
left' :: UnIndexed i p a b -> UnIndexed i p (Either a c) (Either b c)
$cleft' :: forall i (p :: * -> * -> *) a b c.
Choice p =>
UnIndexed i p a b -> UnIndexed i p (Either a c) (Either b c)
$cp1Choice :: forall i (p :: * -> * -> *). Choice p => Profunctor (UnIndexed i p)
Choice, Choice (UnIndexed i p)
Strong (UnIndexed i p)
(Choice (UnIndexed i p), Strong (UnIndexed i p)) =>
(forall (f :: * -> *) a b.
 Traversable f =>
 UnIndexed i p a b -> UnIndexed i p (f a) (f b))
-> (forall a b s t.
    (forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
    -> UnIndexed i p a b -> UnIndexed i p s t)
-> Traversing (UnIndexed i p)
UnIndexed i p a b -> UnIndexed i p (f a) (f b)
(forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
-> UnIndexed i p a b -> UnIndexed i p s t
forall a b s t.
(forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
-> UnIndexed i p a b -> UnIndexed i p s t
forall i (p :: * -> * -> *). Traversing p => Choice (UnIndexed i p)
forall i (p :: * -> * -> *). Traversing p => Strong (UnIndexed i p)
forall i (p :: * -> * -> *) a b s t.
Traversing p =>
(forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
-> UnIndexed i p a b -> UnIndexed i p s t
forall i (p :: * -> * -> *) (f :: * -> *) a b.
(Traversing p, Traversable f) =>
UnIndexed i p a b -> UnIndexed i p (f a) (f b)
forall (f :: * -> *) a b.
Traversable f =>
UnIndexed i p a b -> UnIndexed i p (f a) (f b)
forall (p :: * -> * -> *).
(Choice p, Strong p) =>
(forall (f :: * -> *) a b. Traversable f => p a b -> p (f a) (f b))
-> (forall a b s t.
    (forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
    -> p a b -> p s t)
-> Traversing p
wander :: (forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
-> UnIndexed i p a b -> UnIndexed i p s t
$cwander :: forall i (p :: * -> * -> *) a b s t.
Traversing p =>
(forall (f :: * -> *). Applicative f => (a -> f b) -> s -> f t)
-> UnIndexed i p a b -> UnIndexed i p s t
traverse' :: UnIndexed i p a b -> UnIndexed i p (f a) (f b)
$ctraverse' :: forall i (p :: * -> * -> *) (f :: * -> *) a b.
(Traversing p, Traversable f) =>
UnIndexed i p a b -> UnIndexed i p (f a) (f b)
$cp2Traversing :: forall i (p :: * -> * -> *). Traversing p => Strong (UnIndexed i p)
$cp1Traversing :: forall i (p :: * -> * -> *). Traversing p => Choice (UnIndexed i p)
Traversing, Profunctor (UnIndexed i p)
Profunctor (UnIndexed i p) =>
(forall a d b.
 UnIndexed i p (Either a d) (Either b d) -> UnIndexed i p a b)
-> (forall d a b.
    UnIndexed i p (Either d a) (Either d b) -> UnIndexed i p a b)
-> Cochoice (UnIndexed i p)
UnIndexed i p (Either a d) (Either b d) -> UnIndexed i p a b
UnIndexed i p (Either d a) (Either d b) -> UnIndexed i p a b
forall d a b.
UnIndexed i p (Either d a) (Either d b) -> UnIndexed i p a b
forall a d b.
UnIndexed i p (Either a d) (Either b d) -> UnIndexed i p a b
forall i (p :: * -> * -> *).
Cochoice p =>
Profunctor (UnIndexed i p)
forall i (p :: * -> * -> *) d a b.
Cochoice p =>
UnIndexed i p (Either d a) (Either d b) -> UnIndexed i p a b
forall i (p :: * -> * -> *) a d b.
Cochoice p =>
UnIndexed i p (Either a d) (Either b d) -> UnIndexed i p a b
forall (p :: * -> * -> *).
Profunctor p =>
(forall a d b. p (Either a d) (Either b d) -> p a b)
-> (forall d a b. p (Either d a) (Either d b) -> p a b)
-> Cochoice p
unright :: UnIndexed i p (Either d a) (Either d b) -> UnIndexed i p a b
$cunright :: forall i (p :: * -> * -> *) d a b.
Cochoice p =>
UnIndexed i p (Either d a) (Either d b) -> UnIndexed i p a b
unleft :: UnIndexed i p (Either a d) (Either b d) -> UnIndexed i p a b
$cunleft :: forall i (p :: * -> * -> *) a d b.
Cochoice p =>
UnIndexed i p (Either a d) (Either b d) -> UnIndexed i p a b
$cp1Cochoice :: forall i (p :: * -> * -> *).
Cochoice p =>
Profunctor (UnIndexed i p)
Cochoice, Profunctor (UnIndexed i p)
Profunctor (UnIndexed i p) =>
(forall a d b. UnIndexed i p (a, d) (b, d) -> UnIndexed i p a b)
-> (forall d a b. UnIndexed i p (d, a) (d, b) -> UnIndexed i p a b)
-> Costrong (UnIndexed i p)
UnIndexed i p (a, d) (b, d) -> UnIndexed i p a b
UnIndexed i p (d, a) (d, b) -> UnIndexed i p a b
forall d a b. UnIndexed i p (d, a) (d, b) -> UnIndexed i p a b
forall a d b. UnIndexed i p (a, d) (b, d) -> UnIndexed i p a b
forall i (p :: * -> * -> *).
Costrong p =>
Profunctor (UnIndexed i p)
forall i (p :: * -> * -> *) d a b.
Costrong p =>
UnIndexed i p (d, a) (d, b) -> UnIndexed i p a b
forall i (p :: * -> * -> *) a d b.
Costrong p =>
UnIndexed i p (a, d) (b, d) -> UnIndexed i p a b
forall (p :: * -> * -> *).
Profunctor p =>
(forall a d b. p (a, d) (b, d) -> p a b)
-> (forall d a b. p (d, a) (d, b) -> p a b) -> Costrong p
unsecond :: UnIndexed i p (d, a) (d, b) -> UnIndexed i p a b
$cunsecond :: forall i (p :: * -> * -> *) d a b.
Costrong p =>
UnIndexed i p (d, a) (d, b) -> UnIndexed i p a b
unfirst :: UnIndexed i p (a, d) (b, d) -> UnIndexed i p a b
$cunfirst :: forall i (p :: * -> * -> *) a d b.
Costrong p =>
UnIndexed i p (a, d) (b, d) -> UnIndexed i p a b
$cp1Costrong :: forall i (p :: * -> * -> *).
Costrong p =>
Profunctor (UnIndexed i p)
Costrong)

instance Profunctor p => Profunctor (Indexed i p) where
  dimap :: (a -> b) -> (c -> d) -> Indexed i p b c -> Indexed i p a d
dimap f :: a -> b
f g :: c -> d
g (Indexed p :: p (i, b) c
p) = p (i, a) d -> Indexed i p a d
forall i (p :: * -> * -> *) a b. p (i, a) b -> Indexed i p a b
Indexed (((i, a) -> (i, b)) -> (c -> d) -> p (i, b) c -> p (i, a) d
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap ((a -> b) -> (i, a) -> (i, b)
forall (p :: * -> * -> *) a b c.
Strong p =>
p a b -> p (c, a) (c, b)
second' a -> b
f) c -> d
g p (i, b) c
p)

instance Strong p => Strong (Indexed i p) where
  second' :: Indexed i p a b -> Indexed i p (c, a) (c, b)
second' (Indexed p :: p (i, a) b
p) = p (i, (c, a)) (c, b) -> Indexed i p (c, a) (c, b)
forall i (p :: * -> * -> *) a b. p (i, a) b -> Indexed i p a b
Indexed (((i, (c, a)) -> (c, (i, a)))
-> ((c, b) -> (c, b))
-> p (c, (i, a)) (c, b)
-> p (i, (c, a)) (c, b)
forall (p :: * -> * -> *) a b c d.
Profunctor p =>
(a -> b) -> (c -> d) -> p b c -> p a d
dimap (i, (c, a)) -> (c, (i, a))
forall a a b. (a, (a, b)) -> (a, (a, b))
reassoc (c, b) -> (c, b)
forall a. a -> a
id (p (c, (i, a)) (c, b) -> p (i, (c, a)) (c, b))
-> p (c, (i, a)) (c, b) -> p (i, (c, a)) (c, b)
forall a b. (a -> b) -> a -> b
$ p (i, a) b -> p (c, (i, a)) (c, b)
forall (p :: * -> * -> *) a b c.
Strong p =>
p a b -> p (c, a) (c, b)
second' p (i, a) b
p)
    where
      reassoc :: (a, (a, b)) -> (a, (a, b))
reassoc (i :: a
i, (c :: a
c, a :: b
a)) = (a
c, (a
i, b
a))

instance Profunctor p => Indexable i (Indexed i p) p where
  indexed :: Indexed i p a b -> p (i, a) b
indexed (Indexed p :: p (i, a) b
p) = p (i, a) b
p

instance Profunctor p => Indexable i (UnIndexed i p) p where
  indexed :: UnIndexed i p a b -> p (i, a) b
indexed (UnIndexed p :: p a b
p) = ((i, a) -> a) -> p a b -> p (i, a) b
forall (p :: * -> * -> *) a b c.
Profunctor p =>
(a -> b) -> p b c -> p a c
lmap (i, a) -> a
forall a b. (a, b) -> b
snd p a b
p

instance Indexable i (Forget r) (Forget r) where
instance Functor f => Indexable i (Star f) (Star f) where
instance Functor f => Indexable i (Costar f) (Costar f) where
instance Indexable i (->) (->) where
instance Indexable i Tagged Tagged where