{-# LANGUAGE UndecidableInstances #-} -- required due to instance design

module Language.Fortran.Common.Array where

import Control.DeepSeq ( NFData )
import GHC.Generics ( Generic )
import Data.Data ( Data, Typeable )
import Data.Binary ( Binary )
import Text.PrettyPrint.GenericPretty ( Out(..) )

import qualified Text.PrettyPrint as Pretty

import qualified Language.Fortran.PrettyPrint as F

-- | A single array dimension with bounds of type @a@.
--
--   * @'Num' a => 'Dim' a@ is a static, known-size dimension.
--   * @'Dim' ('Language.Fortran.AST.Expression' '()')@ is a dimension with
--     unevaluated bounds expressions. Note that these bounds may be constant
--     expressions, or refer to dummy variables, or be invalid.
--   * @'Num' a => 'Dim' ('Maybe' a)@ is a dimension where some bounds are
--     known, and others are not. This may be useful to record some information
--     about dynamic explicit-shape arrays.
data Dim a = Dim
  { forall a. Dim a -> a
dimLower :: a -- ^ Dimension lower bound.
  , forall a. Dim a -> a
dimUpper :: a -- ^ Dimension upper bound.
  } deriving stock (Int -> Dim a -> ShowS
forall a. Show a => Int -> Dim a -> ShowS
forall a. Show a => [Dim a] -> ShowS
forall a. Show a => Dim a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Dim a] -> ShowS
$cshowList :: forall a. Show a => [Dim a] -> ShowS
show :: Dim a -> String
$cshow :: forall a. Show a => Dim a -> String
showsPrec :: Int -> Dim a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Dim a -> ShowS
Show, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Dim a) x -> Dim a
forall a x. Dim a -> Rep (Dim a) x
$cto :: forall a x. Rep (Dim a) x -> Dim a
$cfrom :: forall a x. Dim a -> Rep (Dim a) x
Generic, Dim a -> DataType
Dim a -> Constr
forall {a}. Data a => Typeable (Dim a)
forall a. Data a => Dim a -> DataType
forall a. Data a => Dim a -> Constr
forall a. Data a => (forall b. Data b => b -> b) -> Dim a -> Dim a
forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Dim a -> u
forall a u. Data a => (forall d. Data d => d -> u) -> Dim a -> [u]
forall a r r'.
Data a =>
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Dim a -> r
forall a r r'.
Data a =>
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Dim a -> r
forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Dim a -> m (Dim a)
forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Dim a -> m (Dim a)
forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Dim a)
forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Dim a -> c (Dim a)
forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Dim a))
forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Dim a))
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Dim a)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Dim a -> c (Dim a)
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Dim a))
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Dim a -> m (Dim a)
$cgmapMo :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Dim a -> m (Dim a)
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Dim a -> m (Dim a)
$cgmapMp :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Dim a -> m (Dim a)
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Dim a -> m (Dim a)
$cgmapM :: forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Dim a -> m (Dim a)
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Dim a -> u
$cgmapQi :: forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Dim a -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Dim a -> [u]
$cgmapQ :: forall a u. Data a => (forall d. Data d => d -> u) -> Dim a -> [u]
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Dim a -> r
$cgmapQr :: forall a r r'.
Data a =>
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Dim a -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Dim a -> r
$cgmapQl :: forall a r r'.
Data a =>
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Dim a -> r
gmapT :: (forall b. Data b => b -> b) -> Dim a -> Dim a
$cgmapT :: forall a. Data a => (forall b. Data b => b -> b) -> Dim a -> Dim a
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Dim a))
$cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Dim a))
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Dim a))
$cdataCast1 :: forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Dim a))
dataTypeOf :: Dim a -> DataType
$cdataTypeOf :: forall a. Data a => Dim a -> DataType
toConstr :: Dim a -> Constr
$ctoConstr :: forall a. Data a => Dim a -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Dim a)
$cgunfold :: forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Dim a)
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Dim a -> c (Dim a)
$cgfoldl :: forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Dim a -> c (Dim a)
Data, Dim a -> Dim a -> Bool
forall a. Eq a => Dim a -> Dim a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Dim a -> Dim a -> Bool
$c/= :: forall a. Eq a => Dim a -> Dim a -> Bool
== :: Dim a -> Dim a -> Bool
$c== :: forall a. Eq a => Dim a -> Dim a -> Bool
Eq)
    deriving stock (forall a b. a -> Dim b -> Dim a
forall a b. (a -> b) -> Dim a -> Dim b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Dim b -> Dim a
$c<$ :: forall a b. a -> Dim b -> Dim a
fmap :: forall a b. (a -> b) -> Dim a -> Dim b
$cfmap :: forall a b. (a -> b) -> Dim a -> Dim b
Functor, forall a. Eq a => a -> Dim a -> Bool
forall a. Num a => Dim a -> a
forall a. Ord a => Dim a -> a
forall m. Monoid m => Dim m -> m
forall a. Dim a -> Bool
forall a. Dim a -> Int
forall a. Dim a -> [a]
forall a. (a -> a -> a) -> Dim a -> a
forall m a. Monoid m => (a -> m) -> Dim a -> m
forall b a. (b -> a -> b) -> b -> Dim a -> b
forall a b. (a -> b -> b) -> b -> Dim a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: forall a. Num a => Dim a -> a
$cproduct :: forall a. Num a => Dim a -> a
sum :: forall a. Num a => Dim a -> a
$csum :: forall a. Num a => Dim a -> a
minimum :: forall a. Ord a => Dim a -> a
$cminimum :: forall a. Ord a => Dim a -> a
maximum :: forall a. Ord a => Dim a -> a
$cmaximum :: forall a. Ord a => Dim a -> a
elem :: forall a. Eq a => a -> Dim a -> Bool
$celem :: forall a. Eq a => a -> Dim a -> Bool
length :: forall a. Dim a -> Int
$clength :: forall a. Dim a -> Int
null :: forall a. Dim a -> Bool
$cnull :: forall a. Dim a -> Bool
toList :: forall a. Dim a -> [a]
$ctoList :: forall a. Dim a -> [a]
foldl1 :: forall a. (a -> a -> a) -> Dim a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> Dim a -> a
foldr1 :: forall a. (a -> a -> a) -> Dim a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> Dim a -> a
foldl' :: forall b a. (b -> a -> b) -> b -> Dim a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> Dim a -> b
foldl :: forall b a. (b -> a -> b) -> b -> Dim a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> Dim a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> Dim a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> Dim a -> b
foldr :: forall a b. (a -> b -> b) -> b -> Dim a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> Dim a -> b
foldMap' :: forall m a. Monoid m => (a -> m) -> Dim a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> Dim a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> Dim a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> Dim a -> m
fold :: forall m. Monoid m => Dim m -> m
$cfold :: forall m. Monoid m => Dim m -> m
Foldable, Functor Dim
Foldable Dim
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a. Monad m => Dim (m a) -> m (Dim a)
forall (f :: * -> *) a. Applicative f => Dim (f a) -> f (Dim a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Dim a -> m (Dim b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Dim a -> f (Dim b)
sequence :: forall (m :: * -> *) a. Monad m => Dim (m a) -> m (Dim a)
$csequence :: forall (m :: * -> *) a. Monad m => Dim (m a) -> m (Dim a)
mapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Dim a -> m (Dim b)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Dim a -> m (Dim b)
sequenceA :: forall (f :: * -> *) a. Applicative f => Dim (f a) -> f (Dim a)
$csequenceA :: forall (f :: * -> *) a. Applicative f => Dim (f a) -> f (Dim a)
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Dim a -> f (Dim b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Dim a -> f (Dim b)
Traversable)
    deriving anyclass (forall a. NFData a => Dim a -> ()
forall a. (a -> ()) -> NFData a
rnf :: Dim a -> ()
$crnf :: forall a. NFData a => Dim a -> ()
NFData, forall a. Binary a => Get (Dim a)
forall a. Binary a => [Dim a] -> Put
forall a. Binary a => Dim a -> Put
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Dim a] -> Put
$cputList :: forall a. Binary a => [Dim a] -> Put
get :: Get (Dim a)
$cget :: forall a. Binary a => Get (Dim a)
put :: Dim a -> Put
$cput :: forall a. Binary a => Dim a -> Put
Binary)

    -- | This instance is purely for convenience. No definition of ordering is
    --   provided, and the implementation may change at any time.
    deriving stock Dim a -> Dim a -> Bool
Dim a -> Dim a -> Ordering
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 {a}. Ord a => Eq (Dim a)
forall a. Ord a => Dim a -> Dim a -> Bool
forall a. Ord a => Dim a -> Dim a -> Ordering
forall a. Ord a => Dim a -> Dim a -> Dim a
min :: Dim a -> Dim a -> Dim a
$cmin :: forall a. Ord a => Dim a -> Dim a -> Dim a
max :: Dim a -> Dim a -> Dim a
$cmax :: forall a. Ord a => Dim a -> Dim a -> Dim a
>= :: Dim a -> Dim a -> Bool
$c>= :: forall a. Ord a => Dim a -> Dim a -> Bool
> :: Dim a -> Dim a -> Bool
$c> :: forall a. Ord a => Dim a -> Dim a -> Bool
<= :: Dim a -> Dim a -> Bool
$c<= :: forall a. Ord a => Dim a -> Dim a -> Bool
< :: Dim a -> Dim a -> Bool
$c< :: forall a. Ord a => Dim a -> Dim a -> Bool
compare :: Dim a -> Dim a -> Ordering
$ccompare :: forall a. Ord a => Dim a -> Dim a -> Ordering
Ord

-- | Fortran syntax uses @lower:upper@, so only provide an 'Out' instance for
--   that style.
instance Out a => Out (Dim a) where
    doc :: Dim a -> Doc
doc (Dim a
lb a
ub) = forall a. Out a => a -> Doc
doc a
lb forall a. Semigroup a => a -> a -> a
<> Char -> Doc
Pretty.char Char
':' forall a. Semigroup a => a -> a -> a
<> forall a. Out a => a -> Doc
doc a
ub

instance Out (Dim a) => F.Pretty (Dim a) where
    pprint' :: FortranVersion -> Dim a -> Doc
pprint' FortranVersion
_ = forall a. Out a => a -> Doc
doc

-- | Fortran array dimensions, defined by a list of 'Dim's storing lower and
--   upper bounds.
--
-- You select the list type @t@ (which should be 'Functor', 'Foldable' and
-- 'Traversable') and the bound type @a@ (e.g. 'Int').
--
-- Using a non-empty list type such as 'Data.List.NonEmpty.NonEmpty' will
-- disallow representing zero-dimension arrays, providing extra soundness.
--
-- Note the following excerpt from the F2018 standard (8.5.8.2 Explicit-shape
-- array):
--
-- > If the upper bound is less than the lower bound, the range is empty, the
-- > extent in that dimension is zero, and the array is of zero size.
--
-- Note that the 'Foldable' instance does not provide "dimension-like" access to
-- this type. That is, @'length' (a :: 'Dims' t a)@ will _not_ tell you how many
-- dimensions 'a' represents. Use 'dimsLength' for that.
data Dims t a
  -- | Explicit-shape array. All dimensions are known.
  = DimsExplicitShape
      (t (Dim a)) -- ^ list of all dimensions

  -- | Assumed-size array. The final dimension has no upper bound (it is
  --   obtained from its effective argument). Earlier dimensions may be defined
  --   like explicit-shape arrays.
  | DimsAssumedSize
      (Maybe (t (Dim a))) -- ^ list of all dimensions except last
      a                   -- ^ lower bound of last dimension

  -- | Assumed-shape array. Shape is taken from effective argument. We store the
  --   lower bound for each dimension, and thus also the rank (via list length).
  | DimsAssumedShape
      (t a) -- ^ list of lower bounds

    deriving stock (forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (t :: * -> *) a x. Rep (Dims t a) x -> Dims t a
forall (t :: * -> *) a x. Dims t a -> Rep (Dims t a) x
$cto :: forall (t :: * -> *) a x. Rep (Dims t a) x -> Dims t a
$cfrom :: forall (t :: * -> *) a x. Dims t a -> Rep (Dims t a) x
Generic)
    deriving stock (forall a b. a -> Dims t b -> Dims t a
forall a b. (a -> b) -> Dims t a -> Dims t b
forall (t :: * -> *) a b. Functor t => a -> Dims t b -> Dims t a
forall (t :: * -> *) a b.
Functor t =>
(a -> b) -> Dims t a -> Dims t b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Dims t b -> Dims t a
$c<$ :: forall (t :: * -> *) a b. Functor t => a -> Dims t b -> Dims t a
fmap :: forall a b. (a -> b) -> Dims t a -> Dims t b
$cfmap :: forall (t :: * -> *) a b.
Functor t =>
(a -> b) -> Dims t a -> Dims t b
Functor, forall a. Dims t a -> Bool
forall m a. Monoid m => (a -> m) -> Dims t a -> m
forall a b. (a -> b -> b) -> b -> Dims t a -> b
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> Dims t a -> Bool
forall (t :: * -> *) a. (Foldable t, Num a) => Dims t a -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => Dims t a -> a
forall (t :: * -> *) m. (Foldable t, Monoid m) => Dims t m -> m
forall (t :: * -> *) a. Foldable t => Dims t a -> Bool
forall (t :: * -> *) a. Foldable t => Dims t a -> Int
forall (t :: * -> *) a. Foldable t => Dims t a -> [a]
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> a) -> Dims t a -> a
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> Dims t a -> m
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> Dims t a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> Dims t a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: forall a. Num a => Dims t a -> a
$cproduct :: forall (t :: * -> *) a. (Foldable t, Num a) => Dims t a -> a
sum :: forall a. Num a => Dims t a -> a
$csum :: forall (t :: * -> *) a. (Foldable t, Num a) => Dims t a -> a
minimum :: forall a. Ord a => Dims t a -> a
$cminimum :: forall (t :: * -> *) a. (Foldable t, Ord a) => Dims t a -> a
maximum :: forall a. Ord a => Dims t a -> a
$cmaximum :: forall (t :: * -> *) a. (Foldable t, Ord a) => Dims t a -> a
elem :: forall a. Eq a => a -> Dims t a -> Bool
$celem :: forall (t :: * -> *) a. (Foldable t, Eq a) => a -> Dims t a -> Bool
length :: forall a. Dims t a -> Int
$clength :: forall (t :: * -> *) a. Foldable t => Dims t a -> Int
null :: forall a. Dims t a -> Bool
$cnull :: forall (t :: * -> *) a. Foldable t => Dims t a -> Bool
toList :: forall a. Dims t a -> [a]
$ctoList :: forall (t :: * -> *) a. Foldable t => Dims t a -> [a]
foldl1 :: forall a. (a -> a -> a) -> Dims t a -> a
$cfoldl1 :: forall (t :: * -> *) a.
Foldable t =>
(a -> a -> a) -> Dims t a -> a
foldr1 :: forall a. (a -> a -> a) -> Dims t a -> a
$cfoldr1 :: forall (t :: * -> *) a.
Foldable t =>
(a -> a -> a) -> Dims t a -> a
foldl' :: forall b a. (b -> a -> b) -> b -> Dims t a -> b
$cfoldl' :: forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> Dims t a -> b
foldl :: forall b a. (b -> a -> b) -> b -> Dims t a -> b
$cfoldl :: forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> Dims t a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> Dims t a -> b
$cfoldr' :: forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> Dims t a -> b
foldr :: forall a b. (a -> b -> b) -> b -> Dims t a -> b
$cfoldr :: forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> Dims t a -> b
foldMap' :: forall m a. Monoid m => (a -> m) -> Dims t a -> m
$cfoldMap' :: forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> Dims t a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> Dims t a -> m
$cfoldMap :: forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> Dims t a -> m
fold :: forall m. Monoid m => Dims t m -> m
$cfold :: forall (t :: * -> *) m. (Foldable t, Monoid m) => Dims t m -> m
Foldable, forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall {t :: * -> *}. Traversable t => Functor (Dims t)
forall {t :: * -> *}. Traversable t => Foldable (Dims t)
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
Dims t (m a) -> m (Dims t a)
forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
Dims t (f a) -> f (Dims t a)
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> Dims t a -> m (Dims t b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> Dims t a -> f (Dims t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Dims t a -> f (Dims t b)
sequence :: forall (m :: * -> *) a. Monad m => Dims t (m a) -> m (Dims t a)
$csequence :: forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
Dims t (m a) -> m (Dims t a)
mapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> Dims t a -> m (Dims t b)
$cmapM :: forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> Dims t a -> m (Dims t b)
sequenceA :: forall (f :: * -> *) a.
Applicative f =>
Dims t (f a) -> f (Dims t a)
$csequenceA :: forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
Dims t (f a) -> f (Dims t a)
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Dims t a -> f (Dims t b)
$ctraverse :: forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> Dims t a -> f (Dims t b)
Traversable)

-- We have to standalone derive most instances due to the @t@ list-like.
deriving stock instance (Show a, Show (t a), Show (t (Dim a)))
  => Show (Dims t a)
deriving anyclass instance (NFData a, NFData (t a), NFData (t (Dim a)))
  => NFData (Dims t a)
deriving stock instance (Data a, Data (t a), Data (t (Dim a)), Typeable t)
  => Data (Dims t a)
deriving stock instance (Eq a, Eq (t a), Eq (t (Dim a)))
  => Eq (Dims t a)
deriving anyclass instance (Binary a, Binary (t a), Binary (t (Dim a)))
  => Binary (Dims t a)

-- | This instance is purely for convenience. No definition of ordering is
--   provided, and the implementation may change at any time.
deriving stock instance (Ord a, Ord (t a), Ord (t (Dim a)))
  => Ord (Dims t a)

instance (Foldable t, Functor t, Out (Dim a), Out a)
  => Out (Dims t a) where
    docPrec :: Int -> Dims t a -> Doc
docPrec Int
_ = forall a. Out a => a -> Doc
doc
    doc :: Dims t a -> Doc
doc = Doc -> Doc
Pretty.parens forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
      DimsExplicitShape t (Dim a)
ds ->
        forall (t :: * -> *). Foldable t => Doc -> t Doc -> Doc
prettyIntersperse Doc
dimSep forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Out a => a -> Doc
doc t (Dim a)
ds
      DimsAssumedShape t a
ss ->
        forall (t :: * -> *). Foldable t => Doc -> t Doc -> Doc
prettyIntersperse Doc
dimSep forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Out a => a -> Doc
go t a
ss
        where
          go :: a -> Doc
go a
s = forall a. Out a => a -> Doc
doc a
s forall a. Semigroup a => a -> a -> a
<> Char -> Doc
Pretty.char Char
':'
      DimsAssumedSize Maybe (t (Dim a))
mds a
d ->
        -- A bit fragile, but hopefully won't explode on empty 'Just's.
        case Maybe (t (Dim a))
mds of
          Maybe (t (Dim a))
Nothing -> Doc
prettyLast
          Just t (Dim a)
ds -> forall (t :: * -> *). Foldable t => Doc -> t Doc -> Doc
prettyAfter Doc
dimSep (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Out a => a -> Doc
doc t (Dim a)
ds) forall a. Semigroup a => a -> a -> a
<> Doc
prettyLast
        where
          prettyLast :: Doc
prettyLast = forall a. Out a => a -> Doc
doc a
d forall a. Semigroup a => a -> a -> a
<> String -> Doc
Pretty.text String
":*"
      where
        dimSep :: Doc
dimSep = String -> Doc
Pretty.text String
", "

instance Out (Dims t a) => F.Pretty (Dims t a) where
    pprint' :: FortranVersion -> Dims t a -> Doc
pprint' FortranVersion
_ = forall a. Out a => a -> Doc
doc

-- Faster is possible for non @[]@ list-likes, but this is OK for the general
-- case.
prettyIntersperse :: Foldable t => Pretty.Doc -> t Pretty.Doc -> Pretty.Doc
prettyIntersperse :: forall (t :: * -> *). Foldable t => Doc -> t Doc -> Doc
prettyIntersperse Doc
dBetween t Doc
ds =
    case forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\Doc
d -> [Doc
dBetween, Doc
d]) t Doc
ds of
      []    -> forall a. Monoid a => a
mempty
      Doc
_:[Doc]
ds' -> forall a. Monoid a => [a] -> a
mconcat [Doc]
ds'

prettyAfter :: Foldable t => Pretty.Doc -> t Pretty.Doc -> Pretty.Doc
prettyAfter :: forall (t :: * -> *). Foldable t => Doc -> t Doc -> Doc
prettyAfter Doc
dAfter = forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (\Doc
d -> Doc
d forall a. Semigroup a => a -> a -> a
<> Doc
dAfter)

-- | Traverse over the functor in a 'Dims' value with a functor bound type.
--
-- For example, to turn a @'Dims' t ('Maybe' a)@ into a @'Maybe' ('Dims' t a)@.
dimsTraverse :: (Traversable t, Applicative f) => Dims t (f a) -> f (Dims t a)
dimsTraverse :: forall (t :: * -> *) (f :: * -> *) a.
(Traversable t, Applicative f) =>
Dims t (f a) -> f (Dims t a)
dimsTraverse = forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall a. a -> a
id
-- TODO provide a SPECIALIZE clause for the above Maybe case. performance! :)

-- | How many dimensions does the given 'Dims' represent?
dimsLength :: Foldable t => Dims t a -> Int
dimsLength :: forall (t :: * -> *) a. Foldable t => Dims t a -> Int
dimsLength = \case
  DimsExplicitShape t (Dim a)
ds -> forall (t :: * -> *) a. Foldable t => t a -> Int
length t (Dim a)
ds
  DimsAssumedShape t a
ss -> forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
ss
  DimsAssumedSize Maybe (t (Dim a))
mds a
_d ->
    case Maybe (t (Dim a))
mds of
      Maybe (t (Dim a))
Nothing -> Int
1
      Just t (Dim a)
ds -> forall (t :: * -> *) a. Foldable t => t a -> Int
length t (Dim a)
ds forall a. Num a => a -> a -> a
+ Int
1