{-# LANGUAGE CPP, ConstraintKinds, DataKinds, DeriveDataTypeable           #-}
{-# LANGUAGE DeriveFunctor, DeriveTraversable, EmptyDataDecls              #-}
{-# LANGUAGE ExplicitNamespaces, FlexibleContexts, FlexibleInstances       #-}
{-# LANGUAGE GeneralizedNewtypeDeriving, KindSignatures                    #-}
{-# LANGUAGE LiberalTypeSynonyms, MultiParamTypeClasses, PatternSynonyms   #-}
{-# LANGUAGE PolyKinds, RankNTypes, ScopedTypeVariables                    #-}
{-# LANGUAGE StandaloneDeriving, TemplateHaskell, TypeFamilies, TypeInType #-}
{-# LANGUAGE TypeOperators, UndecidableInstances, ViewPatterns             #-}
#if __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ >= 806
{-# LANGUAGE NoStarIsType #-}
#endif
module Data.Sized.Flipped (Flipped(..)) where
import Data.Sized.Internal

import           Control.DeepSeq      (NFData (..))
import           Control.Lens.At      (Index, IxValue, Ixed (..))
import           Control.Lens.TH      (makeWrapped)
import           Control.Lens.Wrapped (_Wrapped)
import           Data.Hashable        (Hashable (..))
import           Data.MonoTraversable (Element, MonoFoldable (..))
import           Data.MonoTraversable (MonoFunctor (..))
import           Data.MonoTraversable (MonoTraversable (..))
import qualified Data.Sequence        as Seq
import qualified Data.Type.Natural    as PN
import           Data.Type.Ordinal    (HasOrdinal, Ordinal (..))
import           Data.Typeable        (Typeable)
import qualified Data.Vector          as V
import qualified Data.Vector.Storable as SV
import qualified Data.Vector.Unboxed  as UV
import qualified GHC.TypeLits         as TL

-- | Wrapper for @'Sized'@ which takes length as its last element, instead of the second.
--
--   Since 0.2.0.0
newtype Flipped f a n = Flipped { Flipped f a n -> Sized f n a
runFlipped :: Sized f n a }
                      deriving (Int -> Flipped f a n -> ShowS
[Flipped f a n] -> ShowS
Flipped f a n -> String
(Int -> Flipped f a n -> ShowS)
-> (Flipped f a n -> String)
-> ([Flipped f a n] -> ShowS)
-> Show (Flipped f a n)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (f :: Type -> Type) a nat (n :: nat).
Show (f a) =>
Int -> Flipped f a n -> ShowS
forall (f :: Type -> Type) a nat (n :: nat).
Show (f a) =>
[Flipped f a n] -> ShowS
forall (f :: Type -> Type) a nat (n :: nat).
Show (f a) =>
Flipped f a n -> String
showList :: [Flipped f a n] -> ShowS
$cshowList :: forall (f :: Type -> Type) a nat (n :: nat).
Show (f a) =>
[Flipped f a n] -> ShowS
show :: Flipped f a n -> String
$cshow :: forall (f :: Type -> Type) a nat (n :: nat).
Show (f a) =>
Flipped f a n -> String
showsPrec :: Int -> Flipped f a n -> ShowS
$cshowsPrec :: forall (f :: Type -> Type) a nat (n :: nat).
Show (f a) =>
Int -> Flipped f a n -> ShowS
Show, Flipped f a n -> Flipped f a n -> Bool
(Flipped f a n -> Flipped f a n -> Bool)
-> (Flipped f a n -> Flipped f a n -> Bool) -> Eq (Flipped f a n)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (f :: Type -> Type) a nat (n :: nat).
Eq (f a) =>
Flipped f a n -> Flipped f a n -> Bool
/= :: Flipped f a n -> Flipped f a n -> Bool
$c/= :: forall (f :: Type -> Type) a nat (n :: nat).
Eq (f a) =>
Flipped f a n -> Flipped f a n -> Bool
== :: Flipped f a n -> Flipped f a n -> Bool
$c== :: forall (f :: Type -> Type) a nat (n :: nat).
Eq (f a) =>
Flipped f a n -> Flipped f a n -> Bool
Eq, Eq (Flipped f a n)
Eq (Flipped f a n)
-> (Flipped f a n -> Flipped f a n -> Ordering)
-> (Flipped f a n -> Flipped f a n -> Bool)
-> (Flipped f a n -> Flipped f a n -> Bool)
-> (Flipped f a n -> Flipped f a n -> Bool)
-> (Flipped f a n -> Flipped f a n -> Bool)
-> (Flipped f a n -> Flipped f a n -> Flipped f a n)
-> (Flipped f a n -> Flipped f a n -> Flipped f a n)
-> Ord (Flipped f a n)
Flipped f a n -> Flipped f a n -> Bool
Flipped f a n -> Flipped f a n -> Ordering
Flipped f a n -> Flipped f a n -> Flipped f a n
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Eq (Flipped f a n)
forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Bool
forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Ordering
forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Flipped f a n
min :: Flipped f a n -> Flipped f a n -> Flipped f a n
$cmin :: forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Flipped f a n
max :: Flipped f a n -> Flipped f a n -> Flipped f a n
$cmax :: forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Flipped f a n
>= :: Flipped f a n -> Flipped f a n -> Bool
$c>= :: forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Bool
> :: Flipped f a n -> Flipped f a n -> Bool
$c> :: forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Bool
<= :: Flipped f a n -> Flipped f a n -> Bool
$c<= :: forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Bool
< :: Flipped f a n -> Flipped f a n -> Bool
$c< :: forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Bool
compare :: Flipped f a n -> Flipped f a n -> Ordering
$ccompare :: forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Ordering
$cp1Ord :: forall (f :: Type -> Type) a nat (n :: nat).
Ord (f a) =>
Eq (Flipped f a n)
Ord, Typeable, Flipped f a n -> ()
(Flipped f a n -> ()) -> NFData (Flipped f a n)
forall a. (a -> ()) -> NFData a
forall (f :: Type -> Type) a nat (n :: nat).
NFData (f a) =>
Flipped f a n -> ()
rnf :: Flipped f a n -> ()
$crnf :: forall (f :: Type -> Type) a nat (n :: nat).
NFData (f a) =>
Flipped f a n -> ()
NFData, Int -> Flipped f a n -> Int
Flipped f a n -> Int
(Int -> Flipped f a n -> Int)
-> (Flipped f a n -> Int) -> Hashable (Flipped f a n)
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
forall (f :: Type -> Type) a nat (n :: nat).
Hashable (f a) =>
Int -> Flipped f a n -> Int
forall (f :: Type -> Type) a nat (n :: nat).
Hashable (f a) =>
Flipped f a n -> Int
hash :: Flipped f a n -> Int
$chash :: forall (f :: Type -> Type) a nat (n :: nat).
Hashable (f a) =>
Flipped f a n -> Int
hashWithSalt :: Int -> Flipped f a n -> Int
$chashWithSalt :: forall (f :: Type -> Type) a nat (n :: nat).
Hashable (f a) =>
Int -> Flipped f a n -> Int
Hashable)

makeWrapped ''Flipped

type instance Index (Flipped f a n) = Ordinal n
type instance IxValue (Flipped f a n) = IxValue (f a)
type instance Element (Flipped f a n) = Element (Sized f n a)
deriving instance MonoFunctor (f a) => MonoFunctor (Flipped f a n)
deriving instance MonoFoldable (f a) => MonoFoldable (Flipped f a n)
instance (MonoTraversable (f a)) => MonoTraversable (Flipped f a n) where
  otraverse :: (Element (Flipped f a n) -> f (Element (Flipped f a n)))
-> Flipped f a n -> f (Flipped f a n)
otraverse = (Sized f n a -> f (Sized f n a))
-> Flipped f a n -> f (Flipped f a n)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
_Wrapped ((Sized f n a -> f (Sized f n a))
 -> Flipped f a n -> f (Flipped f a n))
-> ((Element (f a) -> f (Element (f a)))
    -> Sized f n a -> f (Sized f n a))
-> (Element (f a) -> f (Element (f a)))
-> Flipped f a n
-> f (Flipped f a n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Element (f a) -> f (Element (f a)))
-> Sized f n a -> f (Sized f n a)
forall mono (f :: Type -> Type).
(MonoTraversable mono, Applicative f) =>
(Element mono -> f (Element mono)) -> mono -> f mono
otraverse
  {-# INLINE otraverse #-}

  omapM :: (Element (Flipped f a n) -> m (Element (Flipped f a n)))
-> Flipped f a n -> m (Flipped f a n)
omapM = (Sized f n a -> m (Sized f n a))
-> Flipped f a n -> m (Flipped f a n)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
_Wrapped ((Sized f n a -> m (Sized f n a))
 -> Flipped f a n -> m (Flipped f a n))
-> ((Element (f a) -> m (Element (f a)))
    -> Sized f n a -> m (Sized f n a))
-> (Element (f a) -> m (Element (f a)))
-> Flipped f a n
-> m (Flipped f a n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Element (f a) -> m (Element (f a)))
-> Sized f n a -> m (Sized f n a)
forall mono (f :: Type -> Type).
(MonoTraversable mono, Applicative f) =>
(Element mono -> f (Element mono)) -> mono -> f mono
omapM
  {-# INLINE omapM #-}

instance (Integral (Index (f a)), Ixed (f a), HasOrdinal nat)
      => Ixed (Flipped f a (n :: nat)) where
  {-# SPECIALISE instance Ixed (Flipped [] a (n :: TL.Nat)) #-}
  {-# SPECIALISE instance Ixed (Flipped [] a (n :: PN.Nat)) #-}
  {-# SPECIALISE instance Ixed (Flipped V.Vector a (n :: TL.Nat)) #-}
  {-# SPECIALISE instance Ixed (Flipped V.Vector a (n :: PN.Nat)) #-}
  {-# SPECIALISE instance SV.Storable a => Ixed (Flipped SV.Vector a (n :: TL.Nat)) #-}
  {-# SPECIALISE instance SV.Storable a => Ixed (Flipped SV.Vector a (n :: PN.Nat)) #-}
  {-# SPECIALISE instance UV.Unbox a => Ixed (Flipped UV.Vector a (n :: TL.Nat)) #-}
  {-# SPECIALISE instance UV.Unbox a => Ixed (Flipped UV.Vector a (n :: PN.Nat)) #-}
  {-# SPECIALISE instance Ixed (Flipped Seq.Seq a (n :: TL.Nat)) #-}
  {-# SPECIALISE instance Ixed (Flipped Seq.Seq a (n :: PN.Nat)) #-}
  ix :: Index (Flipped f a n)
-> Traversal' (Flipped f a n) (IxValue (Flipped f a n))
ix Index (Flipped f a n)
o = (Sized f n a -> f (Sized f n a))
-> Flipped f a n -> f (Flipped f a n)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
_Wrapped ((Sized f n a -> f (Sized f n a))
 -> Flipped f a n -> f (Flipped f a n))
-> ((IxValue (f a) -> f (IxValue (f a)))
    -> Sized f n a -> f (Sized f n a))
-> (IxValue (f a) -> f (IxValue (f a)))
-> Flipped f a n
-> f (Flipped f a n)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Sized f n a)
-> Traversal' (Sized f n a) (IxValue (Sized f n a))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index (Sized f n a)
Index (Flipped f a n)
o
  {-# INLINE ix #-}