{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}

-- |
-- Module: Numeric.AffineSpace
-- Copyright: Copyright © 2018 Kadena LLC.
-- License: MIT
-- Maintainer: Lars Kuhtz <lars@kadena.io>
-- Stability: experimental
--
module Numeric.AffineSpace
(
-- * Torsor
  LeftTorsor(..)
, (.+^)
, (^+.)
, (.-.)
, (.-^)

-- * Vector Space
, FractionalVectorSpace(..)

-- * AfficeSpace
, AffineSpace
) where

import Numeric.Additive

-- -------------------------------------------------------------------------- --
-- Torsor

-- | A torsor is a generalization of affine spaces. It doesn't require the
-- underlying structure to be vector space, but an additive group suffices.
-- This means that it doesn't support scalar multiplication. In particular
-- it doesn't require an inverse operation to multiplication, which would
-- add unneeded complexity to the formal definition of the operational
-- semantics.
--
-- A Torsor is also called principal homogeous space.
--
-- prop> zero `add` a == a
-- prop> (a `plus` b) `add` t == a `add` (b `add` t)
-- prop> (s `diff` t) `add` t == s
--
-- The last property is states that `add` is a bijection.
--
class (AdditiveGroup (Diff t)) => LeftTorsor t where
    type Diff t
    add :: Diff t -> t -> t
    diff :: t -> t -> Diff t

instance LeftTorsor Integer where
    type Diff Integer = Integer
    add :: Diff Integer -> Integer -> Integer
add = Integer -> Integer -> Integer
Diff Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+)
    diff :: Integer -> Integer -> Diff Integer
diff = (-)
    {-# INLINE add #-}
    {-# INLINE diff #-}

instance LeftTorsor Rational where
    type Diff Rational = Rational
    add :: Diff Rational -> Rational -> Rational
add = Rational -> Rational -> Rational
Diff Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
(+)
    diff :: Rational -> Rational -> Diff Rational
diff = (-)
    {-# INLINE add #-}
    {-# INLINE diff #-}

infix 6 .-.
(.-.) :: AdditiveAbelianGroup (Diff t) => LeftTorsor t => t -> t -> Diff t
.-. :: forall t.
(AdditiveAbelianGroup (Diff t), LeftTorsor t) =>
t -> t -> Diff t
(.-.) = t -> t -> Diff t
forall t. LeftTorsor t => t -> t -> Diff t
diff

infixl 6 ^+.
(^+.) :: AdditiveAbelianGroup (Diff t) => LeftTorsor t => Diff t -> t -> t
^+. :: forall t.
(AdditiveAbelianGroup (Diff t), LeftTorsor t) =>
Diff t -> t -> t
(^+.) = Diff t -> t -> t
forall t. LeftTorsor t => Diff t -> t -> t
add

infixl 6 .+^
(.+^) :: AdditiveAbelianGroup (Diff t) => LeftTorsor t => t -> Diff t -> t
.+^ :: forall t.
(AdditiveAbelianGroup (Diff t), LeftTorsor t) =>
t -> Diff t -> t
(.+^) = (Diff t -> t -> t) -> t -> Diff t -> t
forall a b c. (a -> b -> c) -> b -> a -> c
flip Diff t -> t -> t
forall t. LeftTorsor t => Diff t -> t -> t
add

infixl 6 .-^
(.-^) :: AdditiveAbelianGroup (Diff t) => LeftTorsor t => t -> Diff t -> t
.-^ :: forall t.
(AdditiveAbelianGroup (Diff t), LeftTorsor t) =>
t -> Diff t -> t
(.-^) t
t Diff t
d = t
t t -> Diff t -> t
forall t.
(AdditiveAbelianGroup (Diff t), LeftTorsor t) =>
t -> Diff t -> t
.+^ Diff t -> Diff t
forall g. AdditiveGroup g => g -> g
invert Diff t
d

-- -------------------------------------------------------------------------- --
-- | Vector Space over Fractional Numbers
--
-- A real vector space is an additive abelian group that forms an module
-- with the field of real numbers.
--
-- prop> a * (b `scale` c) == (a * b) `scale` c
-- prop> 1 `scale` a == a
-- prop> a `scale` (b `plus` c) == (a `scale` b) `plus` (a `scale` c)
-- prop> (a + b) `scale` c == (a `scale` c) `plus` (b `scale` c)
--
class (AdditiveAbelianGroup v, Fractional (Scalar v)) => FractionalVectorSpace v where
    type Scalar v
    scale :: Scalar v -> v -> v

instance FractionalVectorSpace Rational where
    type Scalar Rational = Rational
    scale :: Scalar Rational -> Rational -> Rational
scale = Rational -> Rational -> Rational
Scalar Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
(*)

-- -------------------------------------------------------------------------- --
-- Affine Space

-- | An affine space is a torsor for the action of the additive group
-- of a vector space.
--
type AffineSpace t = (FractionalVectorSpace (Diff t), LeftTorsor t)