{-# 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) = CSequence p -> N
forall x. LengthN x => x -> N
lengthN CSequence p
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[" String -> ShowS
forall a. [a] -> [a] -> [a]
++ ProductSymbol p -> String
forall x. Entity x => ProductSymbol x -> String
psyShow ProductSymbol p
CSequence (Point x)
ps String -> ShowS
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
:<=>: CSequence p -> Statement
forall a. Validable a => a -> Statement
valid CSequence p
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) = p N -> ProductSymbol p -> [(p, N)]
forall (p :: * -> *). p N -> ProductSymbol p -> [(p, N)]
forall (s :: * -> *) i x (p :: * -> *).
Sequence s i x =>
p i -> s x -> [(x, i)]
list p N
p ProductSymbol p
CSequence (Point x)
ps
  Dim CSequence (Point x)
ps ?? :: Dim x p -> N -> Maybe p
?? N
i = ProductSymbol p
CSequence (Point x)
ps ProductSymbol p -> N -> Maybe p
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 = CSequence (Point x) -> Dim x (Point x)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim (CSequence p
CSequence (Point x)
ps CSequence p -> Permutation N -> CSequence p
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) = (CSequence (Point x) -> Dim x (Point x)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim ProductSymbol p
CSequence (Point x)
ps',Permutation N
p) where
    (ProductSymbol p
ps',Permutation N
p) = p N
-> (w -> w -> Ordering)
-> (p -> w)
-> ProductSymbol p
-> (ProductSymbol p, Permutation N)
forall (p :: * -> *) w.
p N
-> (w -> w -> Ordering)
-> (p -> w)
-> ProductSymbol p
-> (ProductSymbol p, Permutation N)
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 ProductSymbol p
CSequence (Point x)
ps

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

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

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

type instance Point (Dim x p) = ()

instance ShowPoint (Dim x p)
instance EqPoint (Dim x p)
instance ValidablePoint (Dim x p)
instance TypeablePoint (Dim x p)
instance SingletonPoint (Dim x p)

instance (Oriented x, Typeable p) => Oriented (Dim x p) where
  orientation :: Dim x p -> Orientation (Point (Dim x p))
orientation Dim x p
_ = ()() -> () -> Orientation ()
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)
_ = CSequence p -> Dim x p
CSequence (Point x) -> Dim x (Point x)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim (CSequence p -> Dim x p) -> CSequence p -> Dim x p
forall (h :: * -> * -> *) x y. Applicative h => h x y -> x -> y
$ Point (CSequence p) -> CSequence p
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 = CSequence (Point x) -> Dim x (Point x)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim (CSequence p
CSequence (Point x)
aCSequence p -> CSequence p -> CSequence p
forall c. Multiplicative c => c -> c -> c
*CSequence p
CSequence (Point x)
b)
  npower :: Dim x p -> N -> Dim x p
npower (Dim CSequence (Point x)
a) N
n = CSequence p -> Dim x p
CSequence (Point x) -> Dim x (Point x)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim (CSequence p -> Dim x p) -> CSequence p -> Dim x p
forall (h :: * -> * -> *) x y. Applicative h => h x y -> x -> y
$ CSequence p -> N -> CSequence p
forall c. Multiplicative c => c -> N -> c
npower CSequence p
CSequence (Point x)
a N
n

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 = CSequence (Point x) -> Dim x (Point x)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim (CSequence p
CSequence (Point x)
a CSequence p -> Exponent (CSequence p) -> CSequence p
forall f. Exponential f => f -> Exponent f -> f
^ Exponent (CSequence p)
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) = ProductSymbol p
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 = ProductSymbol p -> Dim x p
CSequence (Point x) -> Dim x (Point x)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim (ProductSymbol p -> Dim x p)
-> (p -> ProductSymbol p) -> p -> Dim x p
forall y z x. (y -> z) -> (x -> y) -> x -> z
forall (c :: * -> * -> *) y z x.
Category c =>
c y z -> c x y -> c x z
. p -> ProductSymbol p
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 = ProductSymbol p -> Dim x p
CSequence (Point x) -> Dim x (Point x)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim (ProductSymbol p -> Dim x p)
-> ([p] -> ProductSymbol p) -> [p] -> Dim x p
forall y z x. (y -> z) -> (x -> y) -> x -> z
forall (c :: * -> * -> *) y z x.
Category c =>
c y z -> c x y -> c x z
. [p] -> ProductSymbol p
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) = ProductSymbol p -> [(p, N)]
forall x. ProductSymbol x -> [(x, N)]
psyxs ProductSymbol p
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) = ProductSymbol p -> Word N p
forall x. Entity x => ProductSymbol x -> Word N x
psywrd ProductSymbol p
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) = CSequence (Point y) -> Dim y (Point y)
forall x. CSequence (Point x) -> Dim x (Point x)
Dim ((p -> q) -> ProductSymbol p -> ProductSymbol q
forall y x.
Entity y =>
(x -> y) -> ProductSymbol x -> ProductSymbol y
psyMap p -> q
f ProductSymbol p
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 X N -> (N -> X (Dim x ())) -> X (Dim x ())
forall a b. X a -> (a -> X b) -> X b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Dim x () -> X (Dim x ())
forall a. a -> X a
forall (m :: * -> *) a. Monad m => a -> m a
return (Dim x () -> X (Dim x ())) -> (N -> Dim x ()) -> N -> X (Dim x ())
forall y z x. (y -> z) -> (x -> y) -> x -> z
forall (c :: * -> * -> *) y z x.
Category c =>
c y z -> c x y -> c x z
. (() -> Dim x ()
forall p x. (Entity p, p ~ Point x) => p -> Dim x p
dim () Dim x () -> Exponent (Dim x ()) -> Dim x ()
forall f. Exponential f => f -> Exponent f -> f
^)