packages feed

sized-1.0.0.0: src/Data/Sized/Internal.hs

{-# LANGUAGE CPP, ConstraintKinds, DataKinds, DeriveDataTypeable           #-}
{-# LANGUAGE DeriveFunctor, DeriveTraversable, DerivingStrategies          #-}
{-# LANGUAGE ExplicitNamespaces, FlexibleContexts, FlexibleInstances       #-}
{-# LANGUAGE GeneralizedNewtypeDeriving, KindSignatures                    #-}
{-# LANGUAGE LiberalTypeSynonyms, MultiParamTypeClasses, PolyKinds         #-}
{-# LANGUAGE RankNTypes, ScopedTypeVariables, StandaloneDeriving           #-}
{-# LANGUAGE TypeFamilies, TypeInType, TypeOperators, UndecidableInstances #-}
#if __GLASGOW_HASKELL__ && __GLASGOW_HASKELL__ >= 806
{-# LANGUAGE NoStarIsType #-}
#endif
{-# OPTIONS_GHC -fno-warn-orphans #-}
module Data.Sized.Internal (Sized(..)) where
import           Control.DeepSeq      (NFData (..))
import           Control.Lens.At      (Index, IxValue, Ixed (..))
import           Control.Lens.Indexed (FoldableWithIndex (..),
                                       FunctorWithIndex (..),
                                       TraversableWithIndex (..))
import           Control.Subcategory  (CFoldable, CFunctor, Constrained)
import           Data.Hashable        (Hashable (..))
import           Data.Kind            (Type)
import           Data.MonoTraversable (Element, MonoFoldable (..),
                                       MonoFunctor (..), MonoTraversable (..))
import qualified Data.Sequence        as Seq
import           Data.Type.Ordinal    (Ordinal (..), ordToNatural,
                                       unsafeNaturalToOrd)
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           GHC.TypeNats

-- | @Sized@ wraps a sequential type 'f' and makes length-parametrized version.
--
-- Here, 'f' must be the instance of 'CFreeMonoid' (f a) a@ for all @a@.
--
-- Since 0.2.0.0
newtype Sized (f :: Type -> Type) (n :: Nat) a =
  Sized { runSized :: f a
        } deriving (Eq, Ord, Typeable,
                    Functor, Foldable, Traversable)
          deriving newtype
                (Constrained, CFoldable, CFunctor)

type instance Element (Sized f n a) = Element (f a)

-- | Since 0.2.0.0
deriving instance MonoFoldable (f a)
               => MonoFoldable (Sized f n a)

-- | Since 0.2.0.0
deriving instance MonoFunctor (f a)
               => MonoFunctor (Sized f n a)

-- | Since 0.2.0.0
instance {-# OVERLAPPABLE #-} (MonoTraversable (f a))
      => MonoTraversable (Sized f n a) where
  {-# SPECIALISE instance MonoTraversable (Sized [] n a) #-}
  {-# SPECIALISE instance MonoTraversable (Sized V.Vector n a) #-}
  {-# SPECIALISE instance MonoTraversable (Sized Seq.Seq n a) #-}
  {-# SPECIALISE instance UV.Unbox a => MonoTraversable (Sized UV.Vector n a) #-}
  {-# SPECIALISE instance SV.Storable a => MonoTraversable (Sized SV.Vector n a) #-}
  otraverse f = fmap Sized . otraverse f . runSized
  omapM f = fmap Sized . omapM f. runSized

-- | Since 0.6.0.0
instance {-# OVERLAPPING #-} SV.Storable a => MonoTraversable (Sized SV.Vector n a) where
  otraverse f = fmap Sized . otraverse f . runSized
  omapM f = fmap Sized . omapM f . runSized

-- | Since 0.6.0.0
instance {-# OVERLAPPING #-} UV.Unbox a => MonoTraversable (Sized UV.Vector n a) where
  otraverse f = fmap Sized . otraverse f . runSized
  omapM f = fmap Sized . omapM f . runSized

deriving instance NFData (f a) => NFData (Sized f n a)
deriving instance Hashable (f a) => Hashable (Sized f n a)

instance Show (f a) => Show (Sized f n a) where
  showsPrec d (Sized x) = showsPrec d x

-- | Since 0.2.0.0
type instance Index (Sized f n a) = Ordinal n

-- | Since 0.3.0.0
type instance IxValue (Sized f n a) = IxValue (f a)
instance (Integral (Index (f a)), Ixed (f a))
         => Ixed (Sized f (n :: Nat) a) where
  {-# SPECIALISE instance Ixed (Sized [] (n :: Nat) a) #-}
  {-# SPECIALISE instance Ixed (Sized V.Vector (n :: Nat) a) #-}
  {-# SPECIALISE instance SV.Storable a => Ixed (Sized SV.Vector (n :: Nat) a) #-}
  {-# SPECIALISE instance UV.Unbox a => Ixed (Sized UV.Vector (n :: Nat) a) #-}
  {-# SPECIALISE instance Ixed (Sized Seq.Seq (n :: Nat) a) #-}
  {-# INLINE ix #-}
  ix n f = fmap Sized . ix (fromIntegral $ ordToNatural n) f . runSized

-- | Since 0.2.0.0
instance (Integral i, FunctorWithIndex i f, KnownNat n)
      => FunctorWithIndex (Ordinal n) (Sized f n) where
  imap f = Sized . imap (f . unsafeNaturalToOrd . fromIntegral) . runSized
  {-# INLINE imap #-}
  {-# SPECIALISE instance KnownNat n
                       => FunctorWithIndex (Ordinal n) (Sized [] (n :: Nat)) #-}
  {-# SPECIALISE instance KnownNat n
                       => FunctorWithIndex (Ordinal n) (Sized V.Vector (n :: Nat)) #-}
  {-# SPECIALISE instance KnownNat n
                       => FunctorWithIndex (Ordinal n) (Sized Seq.Seq (n :: Nat)) #-}

-- | Since 0.4.0.0
instance {-# OVERLAPPABLE #-}  (Integral i, FoldableWithIndex i f, KnownNat n)
      => FoldableWithIndex (Ordinal n) (Sized f n) where
  ifoldMap f = ifoldMap (f . unsafeNaturalToOrd . fromIntegral) . runSized
  {-# INLINE ifoldMap #-}

  ifoldr f e = ifoldr (f . unsafeNaturalToOrd . fromIntegral) e . runSized
  {-# INLINE ifoldr #-}

  ifoldl f e = ifoldl (f . unsafeNaturalToOrd . fromIntegral) e . runSized
  {-# INLINE ifoldl #-}

  ifoldr' f e = ifoldr' (f . unsafeNaturalToOrd . fromIntegral) e . runSized
  {-# INLINE ifoldr' #-}

  ifoldl' f e = ifoldl' (f . unsafeNaturalToOrd . fromIntegral) e . runSized
  {-# INLINE ifoldl' #-}

  {-# SPECIALISE instance KnownNat n
                       => FoldableWithIndex (Ordinal n) (Sized [] (n :: Nat)) #-}
  {-# SPECIALISE instance KnownNat n
                       => FoldableWithIndex (Ordinal n) (Sized V.Vector (n :: Nat)) #-}
  {-# SPECIALISE instance KnownNat n
                       => FoldableWithIndex (Ordinal n) (Sized Seq.Seq (n :: Nat)) #-}
-- | Since 0.2.0.0
instance (Integral i, TraversableWithIndex i f, KnownNat n)
      => TraversableWithIndex (Ordinal n) (Sized f n) where
  itraverse f = fmap Sized . itraverse (f . unsafeNaturalToOrd . fromIntegral) . runSized
  {-# INLINE itraverse #-}

  {-# SPECIALISE instance KnownNat n
                       => TraversableWithIndex (Ordinal n) (Sized [] (n :: Nat)) #-}
  {-# SPECIALISE instance KnownNat n
                       => TraversableWithIndex (Ordinal n) (Sized V.Vector (n :: Nat)) #-}
  {-# SPECIALISE instance KnownNat n
                       => TraversableWithIndex (Ordinal n) (Sized Seq.Seq (n :: Nat)) #-}