{-# LANGUAGE CPP #-}
#ifdef TRUSTWORTHY
{-# LANGUAGE Trustworthy #-}
#endif
-----------------------------------------------------------------------------
-- |
-- Module      :  Control.Lens.Internal.Iso
-- Copyright   :  (C) 2012-2016 Edward Kmett
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Edward Kmett <ekmett@gmail.com>
-- Stability   :  experimental
-- Portability :  non-portable
--
----------------------------------------------------------------------------
module Control.Lens.Internal.Iso
  ( Exchange(..)
  , Reversing(..)
  ) where

import Data.Profunctor
#ifndef SAFE
import Data.Profunctor.Unsafe
import Control.Lens.Internal.Coerce
#endif
import Data.ByteString       as StrictB
import Data.ByteString.Lazy  as LazyB
import Data.List.NonEmpty    as NonEmpty
import Data.Text             as StrictT
import Data.Text.Lazy        as LazyT
import Data.Vector           as Vector
import Data.Vector.Primitive as Prim
import Data.Vector.Storable  as Storable
import Data.Vector.Unboxed   as Unbox
import Data.Sequence         as Seq

------------------------------------------------------------------------------
-- Isomorphism: Exchange
------------------------------------------------------------------------------

-- | This is used internally by the 'Control.Lens.Iso.Iso' code to provide
-- efficient access to the two functions that make up an isomorphism.
data Exchange a b s t = Exchange (s -> a) (b -> t)

instance Functor (Exchange a b s) where
  fmap :: (a -> b) -> Exchange a b s a -> Exchange a b s b
fmap f :: a -> b
f (Exchange sa :: s -> a
sa bt :: b -> a
bt) = (s -> a) -> (b -> b) -> Exchange a b s b
forall a b s t. (s -> a) -> (b -> t) -> Exchange a b s t
Exchange s -> a
sa (a -> b
f (a -> b) -> (b -> a) -> b -> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> a
bt)
  {-# INLINE fmap #-}

instance Profunctor (Exchange a b) where
  dimap :: (a -> b) -> (c -> d) -> Exchange a b b c -> Exchange a b a d
dimap f :: a -> b
f g :: c -> d
g (Exchange sa :: b -> a
sa bt :: b -> c
bt) = (a -> a) -> (b -> d) -> Exchange a b a d
forall a b s t. (s -> a) -> (b -> t) -> Exchange a b s t
Exchange (b -> a
sa (b -> a) -> (a -> b) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) (c -> d
g (c -> d) -> (b -> c) -> b -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> c
bt)
  {-# INLINE dimap #-}
  lmap :: (a -> b) -> Exchange a b b c -> Exchange a b a c
lmap f :: a -> b
f (Exchange sa :: b -> a
sa bt :: b -> c
bt) = (a -> a) -> (b -> c) -> Exchange a b a c
forall a b s t. (s -> a) -> (b -> t) -> Exchange a b s t
Exchange (b -> a
sa (b -> a) -> (a -> b) -> a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) b -> c
bt
  {-# INLINE lmap #-}
  rmap :: (b -> c) -> Exchange a b a b -> Exchange a b a c
rmap f :: b -> c
f (Exchange sa :: a -> a
sa bt :: b -> b
bt) = (a -> a) -> (b -> c) -> Exchange a b a c
forall a b s t. (s -> a) -> (b -> t) -> Exchange a b s t
Exchange a -> a
sa (b -> c
f (b -> c) -> (b -> b) -> b -> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> b
bt)
  {-# INLINE rmap #-}
#ifndef SAFE
  ( #. ) _ = Exchange a b a b -> Exchange a b a c
forall a b. Coercible a b => b -> a
coerce'
  {-# INLINE ( #. ) #-}
  ( .# ) p :: Exchange a b b c
p _ = Exchange a b b c -> Exchange a b a c
forall a b. Coercible a b => a -> b
coerce Exchange a b b c
p
  {-# INLINE ( .# ) #-}
#endif

------------------------------------------------------------------------------
-- Reversible
------------------------------------------------------------------------------

-- | This class provides a generalized notion of list reversal extended to other containers.
class Reversing t where
  reversing :: t -> t

instance Reversing [a] where
  reversing :: [a] -> [a]
reversing = [a] -> [a]
forall a. [a] -> [a]
Prelude.reverse

instance Reversing (NonEmpty.NonEmpty a) where
  reversing :: NonEmpty a -> NonEmpty a
reversing = NonEmpty a -> NonEmpty a
forall a. NonEmpty a -> NonEmpty a
NonEmpty.reverse

instance Reversing StrictB.ByteString where
  reversing :: ByteString -> ByteString
reversing = ByteString -> ByteString
StrictB.reverse

instance Reversing LazyB.ByteString where
  reversing :: ByteString -> ByteString
reversing = ByteString -> ByteString
LazyB.reverse

instance Reversing StrictT.Text where
  reversing :: Text -> Text
reversing = Text -> Text
StrictT.reverse

instance Reversing LazyT.Text where
  reversing :: Text -> Text
reversing = Text -> Text
LazyT.reverse

instance Reversing (Vector.Vector a) where
  reversing :: Vector a -> Vector a
reversing = Vector a -> Vector a
forall a. Vector a -> Vector a
Vector.reverse

instance Reversing (Seq a) where
  reversing :: Seq a -> Seq a
reversing = Seq a -> Seq a
forall a. Seq a -> Seq a
Seq.reverse

instance Prim a => Reversing (Prim.Vector a) where
  reversing :: Vector a -> Vector a
reversing = Vector a -> Vector a
forall a. Prim a => Vector a -> Vector a
Prim.reverse

instance Unbox a => Reversing (Unbox.Vector a) where
  reversing :: Vector a -> Vector a
reversing = Vector a -> Vector a
forall a. Unbox a => Vector a -> Vector a
Unbox.reverse

instance Storable a => Reversing (Storable.Vector a) where
  reversing :: Vector a -> Vector a
reversing = Vector a -> Vector a
forall a. Storable a => Vector a -> Vector a
Storable.reverse