{-# language DataKinds #-}
{-# language DerivingStrategies #-}
{-# language FlexibleContexts #-}
{-# language GeneralizedNewtypeDeriving #-}
{-# language MagicHash #-}
{-# language PolyKinds #-}
{-# language ScopedTypeVariables #-}
{-# language UnboxedTuples #-}
module Coya
( Coya(..)
, CoyaGroup(..)
, coyaGroup
) where
import Data.Coerce (coerce)
import Data.Group
import Data.Primitive.Types (Prim)
import Data.Semiring (Semiring(..),Ring(..))
import Foreign.Storable (Storable)
import Prelude hiding (Num(..))
import Refined
import Refined.Unsafe (reallyUnsafeRefine)
import qualified GHC.Num as GHCNum
newtype Coya a = Coya { getCoya :: a }
deriving newtype (Eq,Ord,Semiring,Ring)
deriving newtype (GHCNum.Num,Floating,Fractional,Real,RealFloat,RealFrac)
deriving newtype (Storable,Prim)
deriving stock (Show,Read)
instance Floating a => Semigroup (Coya a) where
Coya x <> Coya y = Coya (x ** log y)
{-# inline (<>) #-}
{-# specialise (<>) :: Coya Float -> Coya Float -> Coya Float #-}
{-# specialise (<>) :: Coya Double -> Coya Double -> Coya Double #-}
instance Floating a => Monoid (Coya a) where
mempty = Coya (exp 1)
{-# inline mempty #-}
{-# specialise mempty :: Coya Float #-}
{-# specialise mempty :: Coya Double #-}
newtype CoyaGroup a = CoyaGroup { getCoyaGroup :: Refined (From 1) (Coya a) }
coyaGroup :: forall a. (Ord a, GHCNum.Num a) => a -> Maybe (CoyaGroup a)
coyaGroup a = do
r <- refineThrow (Coya a)
pure (coerce r)
instance (Floating a, Ord a) => Semigroup (CoyaGroup a) where
CoyaGroup r <> CoyaGroup r' = CoyaGroup (reallyUnsafeRefine (unrefine r <> unrefine r'))
instance (Floating a, Ord a) => Monoid (CoyaGroup a) where
mempty = CoyaGroup (reallyUnsafeRefine mempty)
instance (Floating a, Ord a) => Group (CoyaGroup a) where
invert (CoyaGroup x) = CoyaGroup (reallyUnsafeRefine (Coya (exp (1 / log (getCoya (unrefine x))))))