{-# LANGUAGE AllowAmbiguousTypes #-}

module Telescope.Data.Axes where

import GHC.IsList (IsList (..))
import GHC.TypeLits


type Axis = Int


newtype Axes (a :: Major) = Axes {forall (a :: Major). Axes a -> [Axis]
axes :: [Axis]}
  deriving (Axis -> Axes a -> ShowS
[Axes a] -> ShowS
Axes a -> String
(Axis -> Axes a -> ShowS)
-> (Axes a -> String) -> ([Axes a] -> ShowS) -> Show (Axes a)
forall a.
(Axis -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (a :: Major). Axis -> Axes a -> ShowS
forall (a :: Major). [Axes a] -> ShowS
forall (a :: Major). Axes a -> String
$cshowsPrec :: forall (a :: Major). Axis -> Axes a -> ShowS
showsPrec :: Axis -> Axes a -> ShowS
$cshow :: forall (a :: Major). Axes a -> String
show :: Axes a -> String
$cshowList :: forall (a :: Major). [Axes a] -> ShowS
showList :: [Axes a] -> ShowS
Show, Axes a -> Axes a -> Bool
(Axes a -> Axes a -> Bool)
-> (Axes a -> Axes a -> Bool) -> Eq (Axes a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (a :: Major). Axes a -> Axes a -> Bool
$c== :: forall (a :: Major). Axes a -> Axes a -> Bool
== :: Axes a -> Axes a -> Bool
$c/= :: forall (a :: Major). Axes a -> Axes a -> Bool
/= :: Axes a -> Axes a -> Bool
Eq)


data Major = Row | Column


axesRowMajor :: [Axis] -> Axes Row
axesRowMajor :: [Axis] -> Axes 'Row
axesRowMajor = [Axis] -> Axes 'Row
forall (a :: Major). [Axis] -> Axes a
Axes


axesColumnMajor :: [Axis] -> Axes Column
axesColumnMajor :: [Axis] -> Axes 'Column
axesColumnMajor = [Axis] -> Axes 'Column
forall (a :: Major). [Axis] -> Axes a
Axes


toRowMajor :: Axes Column -> Axes Row
toRowMajor :: Axes 'Column -> Axes 'Row
toRowMajor (Axes [Axis]
as) = [Axis] -> Axes 'Row
forall (a :: Major). [Axis] -> Axes a
Axes ([Axis] -> [Axis]
forall a. [a] -> [a]
reverse [Axis]
as)


toColumnMajor :: Axes Row -> Axes Column
toColumnMajor :: Axes 'Row -> Axes 'Column
toColumnMajor (Axes [Axis]
as) = [Axis] -> Axes 'Column
forall (a :: Major). [Axis] -> Axes a
Axes ([Axis] -> [Axis]
forall a. [a] -> [a]
reverse [Axis]
as)


totalItems :: Axes a -> Int
totalItems :: forall (a :: Major). Axes a -> Axis
totalItems (Axes [Axis]
as) = [Axis] -> Axis
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [Axis]
as


instance IsList (Axes Row) where
  type Item (Axes Row) = Axis
  fromList :: [Item (Axes 'Row)] -> Axes 'Row
fromList = [Axis] -> Axes 'Row
[Item (Axes 'Row)] -> Axes 'Row
forall (a :: Major). [Axis] -> Axes a
Axes
  toList :: Axes 'Row -> [Item (Axes 'Row)]
toList (Axes [Axis]
ax) = [Axis]
[Item (Axes 'Row)]
ax


{- | Specify which numbered axis a type represents

> data X
> instance AxisOrder X where
>   axisN = 1
>
> data Y
> instance AxisOrder Y where
>   axisN = 2
-}
class AxisOrder ax where
  axisN :: Natural