-- Copyright (c) 2010-2015, David Amos. All rights reserved.

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}

-- |A module defining the affine plane and its symmetries
module Math.Algebras.AffinePlane where

import Math.Algebra.Field.Base hiding (powers)
import Math.Algebras.VectorSpace
import Math.Algebras.TensorProduct
import Math.Algebras.Structures
import Math.Algebras.Commutative


data XY = X | Y deriving (Eq, Ord)

instance Show XY where show X = "x"; show Y = "y"

x = glexVar X :: GlexPoly Q XY
y = glexVar Y :: GlexPoly Q XY


data ABCD = A | B | C | D deriving (Eq, Ord)

instance Show ABCD where show A = "a"; show B = "b"; show C = "c"; show D = "d"

a,b,c,d :: Monomial m => Vect Q (m ABCD)
a = var A
b = var B
c = var C
d = var D


-- SL2

newtype SL2 v = SL2 (GlexMonomial v) deriving (Eq,Ord)

instance Show v => Show (SL2 v) where show (SL2 m) = show m

instance Algebra Q (SL2 ABCD) where -- to do this for Num k instead of Q we would need a,b,c,d defined for Num k
    unit 0 = zerov -- V []
    unit x = V [(munit,x)] where munit = SL2 (Glex 0 [])
    mult x = x''' where
        x' = mult $ fmap ( \(SL2 a, SL2 b) -> (a,b) ) x -- perform the multiplication in GlexPoly
        x'' = x' %% [a*d-b*c-1] -- :: GlexPoly Q ABCD] -- quotient by ad-bc=1 in GlexPoly Q ABCD
        x''' = fmap SL2 x'' -- ie wrap the monomials up as SL2 again
        -- mmult (Glex si xis) (Glex sj yjs) = Glex (si+sj) $ addmerge xis yjs

sl2Var v = V [(SL2 (Glex 1 [(v,1)]), 1)] -- :: Vect Q (SL2 ABCD)


-- For example:
-- > a*d :: Vect Q (SL2 ABCD)
-- bc+1

instance Monomial SL2 where
    var = sl2Var
    powers (SL2 (Glex _ xis)) = xis



instance Coalgebra Q (SL2 ABCD) where
    counit x = case x `bind` cu of
               V [] -> 0
               V [(SL2 (Glex 0 []), c)] -> c
        where cu A = 1 :: Vect Q (SL2 ABCD)
              cu B = 0
              cu C = 0
              cu D = 1
    comult x = x `bind` cm
        where cm A = a `te` a + b `te` c
              cm B = a `te` b + b `te` d
              cm C = c `te` a + d `te` c
              cm D = c `te` b + d `te` d
-- In other words
-- counit (a b) = (1 0)
--        (c d)   (0 1)
-- comult (a b) = (a1 b1) `te` (a2 b2)
--        (c d)   (c1 d1)      (c2 d2)

instance Bialgebra Q (SL2 ABCD) where {}

instance HopfAlgebra Q (SL2 ABCD) where
    antipode x = x `bind` antipode'
        where antipode' A = d
              antipode' B = b
              antipode' C = c
              antipode' D = a
-- in the GL2 case we would need 1/det factor as well