{-# LANGUAGE CPP #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
#if __GLASGOW_HASKELL__ < 708
{-# LANGUAGE Trustworthy #-}
#endif
module Control.Lens.Internal.Indexed
(
Indexed(..)
, Conjoined(..)
, Indexable(..)
, Indexing(..)
, indexing
, Indexing64(..)
, indexing64
, withIndex
, asIndex
) where
import Prelude ()
import Control.Arrow as Arrow
import qualified Control.Category as C
import Control.Comonad
import Control.Lens.Internal.Prelude
import Control.Lens.Internal.Instances ()
import Control.Monad.Fix
import Data.Distributive
import Data.Functor.Bind
import Data.Int
import Data.Profunctor.Closed
import Data.Profunctor.Rep
#ifndef SAFE
import Control.Lens.Internal.Coerce
#endif
class
( Choice p, Corepresentable p, Comonad (Corep p), Traversable (Corep p)
, Strong p, Representable p, Monad (Rep p), MonadFix (Rep p), Distributive (Rep p)
, Costrong p, ArrowLoop p, ArrowApply p, ArrowChoice p, Closed p
) => Conjoined p where
distrib :: Functor f => p a b -> p (f a) (f b)
distrib = tabulate . collect . sieve
{-# INLINE distrib #-}
conjoined :: ((p ~ (->)) => q (a -> b) r) -> q (p a b) r -> q (p a b) r
conjoined _ r = r
{-# INLINE conjoined #-}
instance Conjoined (->) where
distrib = fmap
{-# INLINE distrib #-}
conjoined l _ = l
{-# INLINE conjoined #-}
class Conjoined p => Indexable i p where
indexed :: p a b -> i -> a -> b
instance Indexable i (->) where
indexed = const
{-# INLINE indexed #-}
newtype Indexed i a b = Indexed { runIndexed :: i -> a -> b }
instance Functor (Indexed i a) where
fmap g (Indexed f) = Indexed $ \i a -> g (f i a)
{-# INLINE fmap #-}
instance Apply (Indexed i a) where
Indexed f <.> Indexed g = Indexed $ \i a -> f i a (g i a)
{-# INLINE (<.>) #-}
instance Applicative (Indexed i a) where
pure b = Indexed $ \_ _ -> b
{-# INLINE pure #-}
Indexed f <*> Indexed g = Indexed $ \i a -> f i a (g i a)
{-# INLINE (<*>) #-}
instance Bind (Indexed i a) where
Indexed f >>- k = Indexed $ \i a -> runIndexed (k (f i a)) i a
{-# INLINE (>>-) #-}
instance Monad (Indexed i a) where
return = pure
{-# INLINE return #-}
Indexed f >>= k = Indexed $ \i a -> runIndexed (k (f i a)) i a
{-# INLINE (>>=) #-}
instance MonadFix (Indexed i a) where
mfix f = Indexed $ \ i a -> let o = runIndexed (f o) i a in o
{-# INLINE mfix #-}
instance Profunctor (Indexed i) where
dimap ab cd ibc = Indexed $ \i -> cd . runIndexed ibc i . ab
{-# INLINE dimap #-}
lmap ab ibc = Indexed $ \i -> runIndexed ibc i . ab
{-# INLINE lmap #-}
rmap bc iab = Indexed $ \i -> bc . runIndexed iab i
{-# INLINE rmap #-}
#ifndef SAFE
( .# ) ibc _ = coerce ibc
{-# INLINE ( .# ) #-}
( #. ) _ = coerce'
{-# INLINE ( #. ) #-}
#endif
instance Closed (Indexed i) where
closed (Indexed iab) = Indexed $ \i xa x -> iab i (xa x)
instance Costrong (Indexed i) where
unfirst (Indexed iadbd) = Indexed $ \i a -> let
(b, d) = iadbd i (a, d)
in b
instance Sieve (Indexed i) ((->) i) where
sieve = flip . runIndexed
{-# INLINE sieve #-}
instance Representable (Indexed i) where
type Rep (Indexed i) = (->) i
tabulate = Indexed . flip
{-# INLINE tabulate #-}
instance Cosieve (Indexed i) ((,) i) where
cosieve = uncurry . runIndexed
{-# INLINE cosieve #-}
instance Corepresentable (Indexed i) where
type Corep (Indexed i) = (,) i
cotabulate = Indexed . curry
{-# INLINE cotabulate #-}
instance Choice (Indexed i) where
right' = right
{-# INLINE right' #-}
instance Strong (Indexed i) where
second' = second
{-# INLINE second' #-}
instance C.Category (Indexed i) where
id = Indexed (const id)
{-# INLINE id #-}
Indexed f . Indexed g = Indexed $ \i -> f i . g i
{-# INLINE (.) #-}
instance Arrow (Indexed i) where
arr f = Indexed (\_ -> f)
{-# INLINE arr #-}
first f = Indexed (Arrow.first . runIndexed f)
{-# INLINE first #-}
second f = Indexed (Arrow.second . runIndexed f)
{-# INLINE second #-}
Indexed f *** Indexed g = Indexed $ \i -> f i *** g i
{-# INLINE (***) #-}
Indexed f &&& Indexed g = Indexed $ \i -> f i &&& g i
{-# INLINE (&&&) #-}
instance ArrowChoice (Indexed i) where
left f = Indexed (left . runIndexed f)
{-# INLINE left #-}
right f = Indexed (right . runIndexed f)
{-# INLINE right #-}
Indexed f +++ Indexed g = Indexed $ \i -> f i +++ g i
{-# INLINE (+++) #-}
Indexed f ||| Indexed g = Indexed $ \i -> f i ||| g i
{-# INLINE (|||) #-}
instance ArrowApply (Indexed i) where
app = Indexed $ \ i (f, b) -> runIndexed f i b
{-# INLINE app #-}
instance ArrowLoop (Indexed i) where
loop (Indexed f) = Indexed $ \i b -> let (c,d) = f i (b, d) in c
{-# INLINE loop #-}
instance Conjoined (Indexed i) where
distrib (Indexed iab) = Indexed $ \i fa -> iab i <$> fa
{-# INLINE distrib #-}
instance i ~ j => Indexable i (Indexed j) where
indexed = runIndexed
{-# INLINE indexed #-}
newtype Indexing f a = Indexing { runIndexing :: Int -> (Int, f a) }
instance Functor f => Functor (Indexing f) where
fmap f (Indexing m) = Indexing $ \i -> case m i of
(j, x) -> (j, fmap f x)
{-# INLINE fmap #-}
instance Apply f => Apply (Indexing f) where
Indexing mf <.> Indexing ma = Indexing $ \i -> case mf i of
(j, ff) -> case ma j of
~(k, fa) -> (k, ff <.> fa)
{-# INLINE (<.>) #-}
instance Applicative f => Applicative (Indexing f) where
pure x = Indexing $ \i -> (i, pure x)
{-# INLINE pure #-}
Indexing mf <*> Indexing ma = Indexing $ \i -> case mf i of
(j, ff) -> case ma j of
~(k, fa) -> (k, ff <*> fa)
{-# INLINE (<*>) #-}
instance Contravariant f => Contravariant (Indexing f) where
contramap f (Indexing m) = Indexing $ \i -> case m i of
(j, ff) -> (j, contramap f ff)
{-# INLINE contramap #-}
instance Semigroup (f a) => Semigroup (Indexing f a) where
Indexing mx <> Indexing my = Indexing $ \i -> case mx i of
(j, x) -> case my j of
~(k, y) -> (k, x <> y)
{-# INLINE (<>) #-}
instance Monoid (f a) => Monoid (Indexing f a) where
mempty = Indexing $ \i -> (i, mempty)
{-# INLINE mempty #-}
mappend (Indexing mx) (Indexing my) = Indexing $ \i -> case mx i of
(j, x) -> case my j of
~(k, y) -> (k, mappend x y)
{-# INLINE mappend #-}
indexing :: Indexable Int p => ((a -> Indexing f b) -> s -> Indexing f t) -> p a (f b) -> s -> f t
indexing l iafb s = snd $ runIndexing (l (\a -> Indexing (\i -> i `seq` (i + 1, indexed iafb i a))) s) 0
{-# INLINE indexing #-}
newtype Indexing64 f a = Indexing64 { runIndexing64 :: Int64 -> (Int64, f a) }
instance Functor f => Functor (Indexing64 f) where
fmap f (Indexing64 m) = Indexing64 $ \i -> case m i of
(j, x) -> (j, fmap f x)
{-# INLINE fmap #-}
instance Apply f => Apply (Indexing64 f) where
Indexing64 mf <.> Indexing64 ma = Indexing64 $ \i -> case mf i of
(j, ff) -> case ma j of
~(k, fa) -> (k, ff <.> fa)
{-# INLINE (<.>) #-}
instance Applicative f => Applicative (Indexing64 f) where
pure x = Indexing64 $ \i -> (i, pure x)
{-# INLINE pure #-}
Indexing64 mf <*> Indexing64 ma = Indexing64 $ \i -> case mf i of
(j, ff) -> case ma j of
~(k, fa) -> (k, ff <*> fa)
{-# INLINE (<*>) #-}
instance Contravariant f => Contravariant (Indexing64 f) where
contramap f (Indexing64 m) = Indexing64 $ \i -> case m i of
(j, ff) -> (j, contramap f ff)
{-# INLINE contramap #-}
indexing64 :: Indexable Int64 p => ((a -> Indexing64 f b) -> s -> Indexing64 f t) -> p a (f b) -> s -> f t
indexing64 l iafb s = snd $ runIndexing64 (l (\a -> Indexing64 (\i -> i `seq` (i + 1, indexed iafb i a))) s) 0
{-# INLINE indexing64 #-}
withIndex :: (Indexable i p, Functor f) => p (i, s) (f (j, t)) -> Indexed i s (f t)
withIndex f = Indexed $ \i a -> snd <$> indexed f i (i, a)
{-# INLINE withIndex #-}
asIndex :: (Indexable i p, Contravariant f, Functor f) => p i (f i) -> Indexed i s (f s)
asIndex f = Indexed $ \i _ -> phantom (indexed f i i)
{-# INLINE asIndex #-}