{-# LANGUAGE NoImplicitPrelude #-}

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE StandaloneDeriving, GeneralizedNewtypeDeriving #-}

-- |
-- Module      : OAlg.Entity.Matrix.Dim
-- Description : dimension for matrices
-- Copyright   : (c) Erich Gut
-- License     : BSD3
-- Maintainer  : zerich.gut@gmail.com
-- 
-- dimension for matrices of @__x__@ as a complete sequence of @'Point' __x__@. 
module OAlg.Entity.Matrix.Dim
  (
    Dim(..), Dim', fromDim
  , dim, productDim
  , dimxs, dimwrd
  , dimMap
  ) where

import Control.Monad

import Data.Typeable
import Data.List ((++))
import OAlg.Prelude

import OAlg.Structure.Oriented
import OAlg.Structure.Multiplicative
import OAlg.Structure.Exponential
import OAlg.Structure.Operational

import OAlg.Entity.Sequence
import OAlg.Entity.Product (Word(..))

--------------------------------------------------------------------------------
-- Dim -

-- | dimension of @__x__@ as a complete sequence of @'Point' __x__@. 
data Dim x p where Dim :: CSequence (Point x) -> Dim x (Point x)

instance LengthN (Dim x p) where
  lengthN :: Dim x p -> N
lengthN (Dim CSequence (Point x)
ps) = forall x. LengthN x => x -> N
lengthN CSequence (Point x)
ps

instance Oriented x => Show (Dim x p) where
  show :: Dim x p -> String
show (Dim CSequence (Point x)
ps) = String
"Dim[" forall a. [a] -> [a] -> [a]
++ forall x. Entity x => ProductSymbol x -> String
psyShow CSequence (Point x)
ps forall a. [a] -> [a] -> [a]
++ String
"]"
  
deriving instance Oriented x => Eq (Dim x p)
deriving instance (Oriented x, OrdPoint x) => Ord (Dim x p)

instance Oriented x => Validable (Dim x p) where
  valid :: Dim x p -> Statement
valid (Dim CSequence (Point x)
ps) = String -> Label
Label String
"Dim" Label -> Statement -> Statement
:<=>: forall a. Validable a => a -> Statement
valid CSequence (Point x)
ps
 
instance (Oriented x, Typeable p) => Entity (Dim x p)

instance Sequence (Dim x) N p where
  list :: forall (p :: * -> *). p N -> Dim x p -> [(p, N)]
list p N
p (Dim CSequence (Point x)
ps) = forall (s :: * -> *) i x (p :: * -> *).
Sequence s i x =>
p i -> s x -> [(x, i)]
list p N
p CSequence (Point x)
ps
  Dim CSequence (Point x)
ps ?? :: Dim x p -> N -> Maybe p
?? N
i = CSequence (Point x)
ps forall (s :: * -> *) i x. Sequence s i x => s x -> i -> Maybe x
?? N
i

instance Entity p => Opr (Permutation N) (Dim x p) where
  Dim CSequence (Point x)
ps <* :: Dim x p -> Permutation N -> Dim x p
<* Permutation N
p = forall x. CSequence (Point x) -> Dim x (Point x)
Dim (CSequence (Point x)
ps forall f x. Opr f x => x -> f -> x
<* Permutation N
p)

instance (Oriented x, Entity p) => TotalOpr (Permutation N) (Dim x p)

instance (Oriented x, Entity p) => PermutableSequence (Dim x) N p where
  permuteBy :: forall (p :: * -> *) w.
p N
-> (w -> w -> Ordering)
-> (p -> w)
-> Dim x p
-> (Dim x p, Permutation N)
permuteBy p N
f w -> w -> Ordering
c p -> w
w (Dim CSequence (Point x)
ps) = (forall x. CSequence (Point x) -> Dim x (Point x)
Dim ProductSymbol p
ps',Permutation N
p) where
    (ProductSymbol p
ps',Permutation N
p) = forall (s :: * -> *) i x (p :: * -> *) w.
PermutableSequence s i x =>
p i
-> (w -> w -> Ordering) -> (x -> w) -> s x -> (s x, Permutation i)
permuteBy p N
f w -> w -> Ordering
c p -> w
w CSequence (Point x)
ps

--------------------------------------------------------------------------------
-- Dim' -

-- | abbreviation for @'Dim' __x__ ('Point' __x__)@.
type Dim' x = Dim x (Point x)

--------------------------------------------------------------------------------
-- Dim - Multiplicative -

instance (Oriented x, Typeable p) => Oriented (Dim x p) where
  type Point (Dim x p) = ()
  orientation :: Dim x p -> Orientation (Point (Dim x p))
orientation Dim x p
_ = ()forall p. p -> p -> Orientation p
:>()

instance (Oriented x, Typeable p, p ~ Point x) => Multiplicative (Dim x p) where
  one :: Point (Dim x p) -> Dim x p
one Point (Dim x p)
_ = forall x. CSequence (Point x) -> Dim x (Point x)
Dim forall (h :: * -> * -> *) a b. Applicative h => h a b -> a -> b
$ forall c. Multiplicative c => Point c -> c
one ()
  Dim CSequence (Point x)
a * :: Dim x p -> Dim x p -> Dim x p
* Dim CSequence (Point x)
b = forall x. CSequence (Point x) -> Dim x (Point x)
Dim (CSequence (Point x)
aforall c. Multiplicative c => c -> c -> c
*CSequence (Point x)
b)
  npower :: Dim x p -> N -> Dim x p
npower (Dim CSequence (Point x)
a) N
n = forall x. CSequence (Point x) -> Dim x (Point x)
Dim forall (h :: * -> * -> *) a b. Applicative h => h a b -> a -> b
$ forall c. Multiplicative c => c -> N -> c
npower CSequence (Point x)
a N
n

instance Total (Dim x p)

instance (Oriented x, Typeable p, p ~ Point x) => Exponential (Dim x p) where
  type Exponent (Dim x p) = N
  Dim CSequence (Point x)
a ^ :: Dim x p -> Exponent (Dim x p) -> Dim x p
^ Exponent (Dim x p)
n = forall x. CSequence (Point x) -> Dim x (Point x)
Dim (CSequence (Point x)
a forall f. Exponential f => f -> Exponent f -> f
^ Exponent (Dim x p)
n)

--------------------------------------------------------------------------------
-- fromDim -

-- | the underlying product.
fromDim :: Dim x p -> ProductSymbol p
fromDim :: forall x p. Dim x p -> ProductSymbol p
fromDim (Dim CSequence (Point x)
d) = CSequence (Point x)
d

--------------------------------------------------------------------------------
-- dim -

-- | constructing a dimension form a point.
dim :: (Entity p, p ~ Point x) => p -> Dim x p
dim :: forall p x. (Entity p, p ~ Point x) => p -> Dim x p
dim = forall x. CSequence (Point x) -> Dim x (Point x)
Dim forall (c :: * -> * -> *) y z x.
Category c =>
c y z -> c x y -> c x z
. forall x. Entity x => x -> ProductSymbol x
sy

--------------------------------------------------------------------------------
-- productDim -

-- | constructing a dimension from a list of points.
productDim :: (Entity p, p ~ Point x) => [p] -> Dim x p
productDim :: forall p x. (Entity p, p ~ Point x) => [p] -> Dim x p
productDim = forall x. CSequence (Point x) -> Dim x (Point x)
Dim forall (c :: * -> * -> *) y z x.
Category c =>
c y z -> c x y -> c x z
. forall x. Entity x => [x] -> ProductSymbol x
productSymbol

--------------------------------------------------------------------------------
-- dimxs -

-- | the indexed listing of the points.
dimxs :: p ~ Point x => Dim x p -> [(p,N)]
dimxs :: forall p x. (p ~ Point x) => Dim x p -> [(p, N)]
dimxs (Dim CSequence (Point x)
d) = forall x. ProductSymbol x -> [(x, N)]
psyxs CSequence (Point x)
d

--------------------------------------------------------------------------------
-- dimwrd -

-- | the underlying word.
dimwrd :: (Entity p, p ~ Point x) => Dim x p -> Word N p
dimwrd :: forall p x. (Entity p, p ~ Point x) => Dim x p -> Word N p
dimwrd (Dim CSequence (Point x)
d) = forall x. Entity x => ProductSymbol x -> Word N x
psywrd CSequence (Point x)
d

--------------------------------------------------------------------------------
-- dimMap -

-- | mapping a dimension.
dimMap :: (Entity q, q ~ Point y) => (p -> q) -> Dim x p -> Dim y q
dimMap :: forall q y p x.
(Entity q, q ~ Point y) =>
(p -> q) -> Dim x p -> Dim y q
dimMap p -> q
f (Dim CSequence (Point x)
d) = forall x. CSequence (Point x) -> Dim x (Point x)
Dim (forall y x.
Entity y =>
(x -> y) -> ProductSymbol x -> ProductSymbol y
psyMap p -> q
f CSequence (Point x)
d)


--------------------------------------------------------------------------------
-- Dim - XStandard -

instance (Oriented x, () ~ Point x) => XStandard (Dim x ()) where
  xStandard :: X (Dim x ())
xStandard = N -> N -> X N
xNB N
0 N
20 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *) a. Monad m => a -> m a
return forall (c :: * -> * -> *) y z x.
Category c =>
c y z -> c x y -> c x z
. (forall p x. (Entity p, p ~ Point x) => p -> Dim x p
dim () forall f. Exponential f => f -> Exponent f -> f
^)