module Algebra.Structure.SemiRing where
import Control.DeepSeq (NFData(..))
import Data.Coerce
import Data.Monoid hiding ((<>))
import Data.Semigroup
import Data.Vector.Unboxed.Deriving
import Data.Vector.Unboxed (Unbox)
import GHC.Generics
import Unsafe.Coerce
import Numeric.Limits
class SemiRing a where
srplus ∷ a → a → a
srmul ∷ a → a → a
srzero ∷ a
srone ∷ a
infixl 6 ⊕
infixl 6 `srplus`
(⊕) ∷ SemiRing a ⇒ a → a → a
(⊕) = srplus
{-# Inline (⊕) #-}
infixl 7 ⊗
infixl 7 `srmul`
(⊗) ∷ SemiRing a ⇒ a → a → a
(⊗) = srmul
{-# Inline (⊗) #-}
newtype Viterbi x = Viterbi { getViterbi ∷ x }
deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num)
derivingUnbox "Viterbi"
[t| forall x . Unbox x ⇒ Viterbi x → x |] [| getViterbi |] [| Viterbi |]
instance NFData x ⇒ NFData (Viterbi x) where
rnf (Viterbi x) = rnf x
{-# Inline rnf #-}
instance (Ord x, Num x) ⇒ SemiRing (Viterbi x) where
srplus (Viterbi x) (Viterbi y) = Viterbi $ max x y
srmul (Viterbi x) (Viterbi y) = Viterbi $ x * y
srzero = Viterbi 0
srone = Viterbi 1
{-# Inline srplus #-}
{-# Inline srmul #-}
{-# Inline srzero #-}
{-# Inline srone #-}
newtype MinPlus x = MinPlus { getMinPlus ∷ x }
deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num)
derivingUnbox "MinPlus"
[t| forall x . Unbox x ⇒ MinPlus x → x |] [| getMinPlus |] [| MinPlus |]
instance NFData x ⇒ NFData (MinPlus x) where
rnf (MinPlus x) = rnf x
{-# Inline rnf #-}
instance (Ord x, Num x, NumericLimits x) ⇒ SemiRing (MinPlus x) where
srplus (MinPlus x) (MinPlus y) = MinPlus $ min x y
srmul (MinPlus x) (MinPlus y) = MinPlus $ x + y
srzero = MinPlus maxFinite
srone = 0
{-# Inline srplus #-}
{-# Inline srmul #-}
{-# Inline srzero #-}
{-# Inline srone #-}
newtype MaxPlus x = MaxPlus { getMaxPlus ∷ x }
deriving (Eq, Ord, Read, Show, Bounded, Generic, Generic1, Num)
derivingUnbox "MaxPlus"
[t| forall x . Unbox x ⇒ MaxPlus x → x |] [| getMaxPlus |] [| MaxPlus |]
instance NFData x ⇒ NFData (MaxPlus x) where
rnf (MaxPlus x) = rnf x
{-# Inline rnf #-}
instance NumericLimits x ⇒ NumericLimits (MaxPlus x) where
minFinite = MaxPlus minFinite
maxFinite = MaxPlus maxFinite
instance (Ord x, Num x, NumericLimits x) ⇒ SemiRing (MaxPlus x) where
srplus (MaxPlus x) (MaxPlus y) = MaxPlus $ max x y
srmul (MaxPlus x) (MaxPlus y) = MaxPlus $ x + y
srzero = MaxPlus minFinite
srone = 0
{-# Inline srplus #-}
{-# Inline srmul #-}
{-# Inline srzero #-}
{-# Inline srone #-}
newtype GSemiRing (zeroMonoid ∷ * → *) (oneMonoid ∷ * → *) (x ∷ *) = GSemiRing { getSemiRing ∷ x }
deriving (Eq, Ord, Read, Show, Generic)
instance
forall zeroMonoid oneMonoid x
. ( Semigroup (zeroMonoid x)
, Monoid (zeroMonoid x)
, Semigroup ( oneMonoid x)
, Monoid ( oneMonoid x)
)
⇒ SemiRing (GSemiRing zeroMonoid oneMonoid x) where
srplus (GSemiRing x) (GSemiRing y) =
let x' ∷ zeroMonoid x = unsafeCoerce x
y' ∷ zeroMonoid x = unsafeCoerce y
in unsafeCoerce $ x' <> y'
srmul (GSemiRing x) (GSemiRing y) =
let x' ∷ oneMonoid x = unsafeCoerce x
y' ∷ oneMonoid x = unsafeCoerce y
in unsafeCoerce $ x' <> y'
srzero = unsafeCoerce (mempty ∷ zeroMonoid x)
srone = unsafeCoerce (mempty ∷ oneMonoid x)
{-# Inline srplus #-}
{-# Inline srmul #-}
{-# Inline srzero #-}
{-# Inline srone #-}