{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LiberalTypeSynonyms #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}

#if __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ >= 806
{-# LANGUAGE NoStarIsType #-}
#endif
module Data.Sized.Flipped (Flipped (..)) where

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 (..), MonoFunctor (..), MonoTraversable (..))
import qualified Data.Sequence as Seq
import Data.Sized.Internal
import qualified Data.Type.Natural as PN
import Data.Type.Ordinal (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 (n :: Nat).
Show (f a) =>
Int -> Flipped f a n -> ShowS
forall (f :: Type -> Type) a (n :: Nat).
Show (f a) =>
[Flipped f a n] -> ShowS
forall (f :: Type -> Type) a (n :: Nat).
Show (f a) =>
Flipped f a n -> String
showList :: [Flipped f a n] -> ShowS
$cshowList :: forall (f :: Type -> Type) a (n :: Nat).
Show (f a) =>
[Flipped f a n] -> ShowS
show :: Flipped f a n -> String
$cshow :: forall (f :: Type -> Type) a (n :: Nat).
Show (f a) =>
Flipped f a n -> String
showsPrec :: Int -> Flipped f a n -> ShowS
$cshowsPrec :: forall (f :: Type -> Type) a (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 (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 (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 (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 (n :: Nat).
Ord (f a) =>
Eq (Flipped f a n)
forall (f :: Type -> Type) a (n :: Nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Bool
forall (f :: Type -> Type) a (n :: Nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Ordering
forall (f :: Type -> Type) a (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 (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 (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 (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 (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 (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 (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 (n :: Nat).
Ord (f a) =>
Flipped f a n -> Flipped f a n -> Ordering
$cp1Ord :: forall (f :: Type -> Type) a (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 (n :: Nat).
NFData (f a) =>
Flipped f a n -> ()
rnf :: Flipped f a n -> ()
$crnf :: forall (f :: Type -> Type) a (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 (n :: Nat).
Hashable (f a) =>
Int -> Flipped f a n -> Int
forall (f :: Type -> Type) a (n :: Nat).
Hashable (f a) =>
Flipped f a n -> Int
hash :: Flipped f a n -> Int
$chash :: forall (f :: Type -> Type) a (n :: Nat).
Hashable (f a) =>
Flipped f a n -> Int
hashWithSalt :: Int -> Flipped f a n -> Int
$chashWithSalt :: forall (f :: Type -> Type) a (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)) =>
  Ixed (Flipped f a n)
  where
  {-# SPECIALIZE instance Ixed (Flipped [] a (n :: TL.Nat)) #-}
  {-# SPECIALIZE instance Ixed (Flipped [] a (n :: PN.Nat)) #-}
  {-# SPECIALIZE instance Ixed (Flipped V.Vector a (n :: TL.Nat)) #-}
  {-# SPECIALIZE instance Ixed (Flipped V.Vector a (n :: PN.Nat)) #-}
  {-# SPECIALIZE instance SV.Storable a => Ixed (Flipped SV.Vector a (n :: TL.Nat)) #-}
  {-# SPECIALIZE instance SV.Storable a => Ixed (Flipped SV.Vector a (n :: PN.Nat)) #-}
  {-# SPECIALIZE instance UV.Unbox a => Ixed (Flipped UV.Vector a (n :: TL.Nat)) #-}
  {-# SPECIALIZE instance UV.Unbox a => Ixed (Flipped UV.Vector a (n :: PN.Nat)) #-}
  {-# SPECIALIZE instance Ixed (Flipped Seq.Seq a (n :: TL.Nat)) #-}
  {-# SPECIALIZE 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 #-}