{-# LANGUAGE TypeFamilies #-}

{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}

-- |
-- Module      : OAlg.Data.Dualisable
-- Description : concept of duality
-- Copyright   : (c) Erich Gut
-- License     : BSD3
-- Maintainer  : zerich.gut@gmail.com
-- 
-- data admitting a kind of duality.
module OAlg.Data.Dualisable
  ( -- * Dual
    Dual

    -- * Dualisable
  , Dualisable(..), fromDual'

    -- * Reflexive
  , Reflexive(..), fromBidual'

    -- * Transposable
  , Transposable(..)

    -- * Site
  , Site(..)

    -- * Side
  , Side(..)

    -- * Direction
  , Direction(..)
  )
  where

--------------------------------------------------------------------------------
-- Dual -

-- | the assigned dual kind.
type family Dual (x :: k) :: k

--------------------------------------------------------------------------------
-- Dualisable -

-- | admitting a duality.
--
--   __Property__ Let __@x@__ be 'Dualisable', than holds: 'toDual' is a bijection
--   with its inverse 'fromDual'.
class Dualisable x where
  toDual   :: x -> Dual x
  fromDual :: Dual x -> x

--------------------------------------------------------------------------------
-- fromDual' -

-- | 'fromDual' enriched with a parameterized type __@p@__ which serves as a proxy -
--   e.g. 'Data.Proxy.Proxy' or 'OAlg.Data.Identity.Id' will serve - and will not be evaluated.
--   It serves for the type checker to pick the right 'fromDual'.
fromDual' :: Dualisable x => p x -> Dual x -> x
fromDual' :: forall x (p :: * -> *). Dualisable x => p x -> Dual x -> x
fromDual' p x
_ = forall x. Dualisable x => Dual x -> x
fromDual

--------------------------------------------------------------------------------
-- Reflexive -

-- | admitting reflection.
--
--   __Property__ Let __@x@__ be 'Reflexive', than holds:
--
--   (1) 'toBidual' is a bijection with its inverse 'fromBidual'.
class Reflexive x where
  toBidual   :: x -> Dual (Dual x)
  fromBidual :: Dual (Dual x) -> x

-- | 'fromBidual' enriched with a parameterized type __@p@__ which serves as a proxy -
--   e.g. 'Proxy' or 'OAlg.Data.Identity.Id' will serve - and will not be evaluated.
--   It serves for the type checker to pick the right 'fromBidual'.
fromBidual' :: Reflexive x => p x -> Dual (Dual x) -> x
fromBidual' :: forall x (p :: * -> *). Reflexive x => p x -> Dual (Dual x) -> x
fromBidual' p x
_ = forall x. Reflexive x => Dual (Dual x) -> x
fromBidual

--------------------------------------------------------------------------------
-- Transposable -

-- | transposable types..
--
--   __Property__ Let __@x@__ be a 'Transposable', then holds:
--  For all @x@ in __@x@__ holds: @'transpose' ('transpose' x) '==' x@.
class Transposable x where 
  transpose :: x -> x

--------------------------------------------------------------------------------
-- Site -

-- | concept of the sites 'From' and 'To'.
data Site = From | To deriving (Int -> Site -> ShowS
[Site] -> ShowS
Site -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Site] -> ShowS
$cshowList :: [Site] -> ShowS
show :: Site -> String
$cshow :: Site -> String
showsPrec :: Int -> Site -> ShowS
$cshowsPrec :: Int -> Site -> ShowS
Show,Site -> Site -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Site -> Site -> Bool
$c/= :: Site -> Site -> Bool
== :: Site -> Site -> Bool
$c== :: Site -> Site -> Bool
Eq,Eq Site
Site -> Site -> Bool
Site -> Site -> Ordering
Site -> Site -> Site
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
min :: Site -> Site -> Site
$cmin :: Site -> Site -> Site
max :: Site -> Site -> Site
$cmax :: Site -> Site -> Site
>= :: Site -> Site -> Bool
$c>= :: Site -> Site -> Bool
> :: Site -> Site -> Bool
$c> :: Site -> Site -> Bool
<= :: Site -> Site -> Bool
$c<= :: Site -> Site -> Bool
< :: Site -> Site -> Bool
$c< :: Site -> Site -> Bool
compare :: Site -> Site -> Ordering
$ccompare :: Site -> Site -> Ordering
Ord,Int -> Site
Site -> Int
Site -> [Site]
Site -> Site
Site -> Site -> [Site]
Site -> Site -> Site -> [Site]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Site -> Site -> Site -> [Site]
$cenumFromThenTo :: Site -> Site -> Site -> [Site]
enumFromTo :: Site -> Site -> [Site]
$cenumFromTo :: Site -> Site -> [Site]
enumFromThen :: Site -> Site -> [Site]
$cenumFromThen :: Site -> Site -> [Site]
enumFrom :: Site -> [Site]
$cenumFrom :: Site -> [Site]
fromEnum :: Site -> Int
$cfromEnum :: Site -> Int
toEnum :: Int -> Site
$ctoEnum :: Int -> Site
pred :: Site -> Site
$cpred :: Site -> Site
succ :: Site -> Site
$csucc :: Site -> Site
Enum,Site
forall a. a -> a -> Bounded a
maxBound :: Site
$cmaxBound :: Site
minBound :: Site
$cminBound :: Site
Bounded)

type instance Dual From = To
type instance Dual To = From

instance Transposable Site where
  transpose :: Site -> Site
transpose Site
From = Site
To
  transpose Site
To = Site
From

--------------------------------------------------------------------------------
-- Side -

-- | concept of sides 'LeftSide' and 'RightSide'
data Side = LeftSide | RightSide deriving (Int -> Side -> ShowS
[Side] -> ShowS
Side -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Side] -> ShowS
$cshowList :: [Side] -> ShowS
show :: Side -> String
$cshow :: Side -> String
showsPrec :: Int -> Side -> ShowS
$cshowsPrec :: Int -> Side -> ShowS
Show,Side -> Side -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Side -> Side -> Bool
$c/= :: Side -> Side -> Bool
== :: Side -> Side -> Bool
$c== :: Side -> Side -> Bool
Eq,Eq Side
Side -> Side -> Bool
Side -> Side -> Ordering
Side -> Side -> Side
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
min :: Side -> Side -> Side
$cmin :: Side -> Side -> Side
max :: Side -> Side -> Side
$cmax :: Side -> Side -> Side
>= :: Side -> Side -> Bool
$c>= :: Side -> Side -> Bool
> :: Side -> Side -> Bool
$c> :: Side -> Side -> Bool
<= :: Side -> Side -> Bool
$c<= :: Side -> Side -> Bool
< :: Side -> Side -> Bool
$c< :: Side -> Side -> Bool
compare :: Side -> Side -> Ordering
$ccompare :: Side -> Side -> Ordering
Ord,Int -> Side
Side -> Int
Side -> [Side]
Side -> Side
Side -> Side -> [Side]
Side -> Side -> Side -> [Side]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Side -> Side -> Side -> [Side]
$cenumFromThenTo :: Side -> Side -> Side -> [Side]
enumFromTo :: Side -> Side -> [Side]
$cenumFromTo :: Side -> Side -> [Side]
enumFromThen :: Side -> Side -> [Side]
$cenumFromThen :: Side -> Side -> [Side]
enumFrom :: Side -> [Side]
$cenumFrom :: Side -> [Side]
fromEnum :: Side -> Int
$cfromEnum :: Side -> Int
toEnum :: Int -> Side
$ctoEnum :: Int -> Side
pred :: Side -> Side
$cpred :: Side -> Side
succ :: Side -> Side
$csucc :: Side -> Side
Enum,Side
forall a. a -> a -> Bounded a
maxBound :: Side
$cmaxBound :: Side
minBound :: Side
$cminBound :: Side
Bounded)

type instance Dual LeftSide = RightSide
type instance Dual RightSide = LeftSide

instance Transposable Side where
  transpose :: Side -> Side
transpose Side
LeftSide = Side
RightSide
  transpose Side
RightSide = Side
LeftSide

--------------------------------------------------------------------------------
-- Direction -

-- | concept of the directions 'LeftToRight' and 'RightToLeft'.
data Direction = LeftToRight | RightToLeft deriving (Int -> Direction -> ShowS
[Direction] -> ShowS
Direction -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Direction] -> ShowS
$cshowList :: [Direction] -> ShowS
show :: Direction -> String
$cshow :: Direction -> String
showsPrec :: Int -> Direction -> ShowS
$cshowsPrec :: Int -> Direction -> ShowS
Show,Direction -> Direction -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Direction -> Direction -> Bool
$c/= :: Direction -> Direction -> Bool
== :: Direction -> Direction -> Bool
$c== :: Direction -> Direction -> Bool
Eq,Eq Direction
Direction -> Direction -> Bool
Direction -> Direction -> Ordering
Direction -> Direction -> Direction
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
min :: Direction -> Direction -> Direction
$cmin :: Direction -> Direction -> Direction
max :: Direction -> Direction -> Direction
$cmax :: Direction -> Direction -> Direction
>= :: Direction -> Direction -> Bool
$c>= :: Direction -> Direction -> Bool
> :: Direction -> Direction -> Bool
$c> :: Direction -> Direction -> Bool
<= :: Direction -> Direction -> Bool
$c<= :: Direction -> Direction -> Bool
< :: Direction -> Direction -> Bool
$c< :: Direction -> Direction -> Bool
compare :: Direction -> Direction -> Ordering
$ccompare :: Direction -> Direction -> Ordering
Ord,Int -> Direction
Direction -> Int
Direction -> [Direction]
Direction -> Direction
Direction -> Direction -> [Direction]
Direction -> Direction -> Direction -> [Direction]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Direction -> Direction -> Direction -> [Direction]
$cenumFromThenTo :: Direction -> Direction -> Direction -> [Direction]
enumFromTo :: Direction -> Direction -> [Direction]
$cenumFromTo :: Direction -> Direction -> [Direction]
enumFromThen :: Direction -> Direction -> [Direction]
$cenumFromThen :: Direction -> Direction -> [Direction]
enumFrom :: Direction -> [Direction]
$cenumFrom :: Direction -> [Direction]
fromEnum :: Direction -> Int
$cfromEnum :: Direction -> Int
toEnum :: Int -> Direction
$ctoEnum :: Int -> Direction
pred :: Direction -> Direction
$cpred :: Direction -> Direction
succ :: Direction -> Direction
$csucc :: Direction -> Direction
Enum,Direction
forall a. a -> a -> Bounded a
maxBound :: Direction
$cmaxBound :: Direction
minBound :: Direction
$cminBound :: Direction
Bounded)

type instance Dual LeftToRight = RightToLeft
type instance Dual RightToLeft = LeftToRight

instance Transposable Direction where
  transpose :: Direction -> Direction
transpose Direction
LeftToRight = Direction
RightToLeft
  transpose Direction
RightToLeft = Direction
LeftToRight