module Text.PhonotacticLearner.Util.Ring (
Additive(..)
, AdditiveGroup(..)
, Semiring(..)
, Ring
, RSum(..), RProd(..)
, sumR, productR
, RingModule(..)
, Vec(..), coords, fromInts, vec
, innerProd, normVec, normalizeVec, consVec
, l1Vec, dl1Vec
, showFVec
) where
import Numeric
import qualified Data.Vector.Unboxed as V
import Control.DeepSeq
import Data.Monoid
class Additive g where
zero :: g
(⊕) :: g -> g -> g
class (Additive g) => AdditiveGroup g where
addinv :: g -> g
(⊖) :: g -> g -> g
x ⊖ y = x ⊕ addinv y
class (Additive r) => Semiring r where
one :: r
(⊗) :: r -> r -> r
class (Semiring r, AdditiveGroup r) => Ring r
class (Ring r, AdditiveGroup v) => RingModule r v where
(⊙) :: r -> v -> v
instance (Ring r) => RingModule r r where
(⊙) = (⊗)
instance Additive () where
zero = ()
() ⊕ () = ()
instance Semiring () where
one = ()
() ⊗ () = ()
instance AdditiveGroup () where
addinv () = ()
() ⊖ () = ()
instance Ring ()
instance Additive Bool where
zero = False
(⊕) = (||)
instance Semiring Bool where
one = True
(⊗) = (&&)
instance (Num r) => Additive r where
zero = 0
(⊕) = (+)
instance (Num r) => Semiring r where
one = 1
(⊗) = (*)
instance (Num r) => AdditiveGroup r where
addinv = negate
(⊖) = ()
instance (Num r) => Ring r
instance (Additive r, Additive s) => Additive (r,s) where
zero = (zero,zero)
(a,b) ⊕ (c,d) = (a ⊕ c, b ⊕ d)
instance (Semiring r, Semiring s) => Semiring (r,s) where
one = (one,one)
(a,b) ⊗ (c,d) = (a ⊗ c, b ⊗ d)
instance (AdditiveGroup r, AdditiveGroup s) => AdditiveGroup (r,s) where
addinv (a,b) = (addinv a, addinv b)
(a,b) ⊖ (c,d) = (a ⊖ c, b ⊖ d)
instance (Ring r, Ring s) => Ring (r,s)
instance (RingModule r v, RingModule r w) => RingModule r (v,w) where
a ⊙ (b,c) = (a ⊙ b, a ⊙ c)
newtype RSum r = RSum r deriving (Ord, Eq, Show, Additive, AdditiveGroup, Semiring, Ring)
newtype RProd r = RProd r deriving (Ord, Eq, Show, Additive, AdditiveGroup, Semiring, Ring)
instance (Additive r) => Monoid (RSum r) where
mempty = RSum zero
(RSum a) `mappend` (RSum b) = RSum (a ⊕ b)
instance (Semiring r) => Monoid (RProd r) where
mempty = RProd one
(RProd a) `mappend` (RProd b) = RProd (a ⊗ b)
sumR :: (Foldable f, Additive r) => f r -> r
sumR xs = let (RSum x) = foldMap RSum xs in x
productR :: (Foldable f, Semiring r) => f r -> r
productR xs = let (RProd x) = foldMap RProd xs in x
instance RingModule Int Double where
x ⊙ y = fromIntegral x * y
newtype Vec = Vec {unVec :: V.Vector Double} deriving (Eq, Read, Show, NFData)
coords :: Vec -> [Double]
coords (Vec xs) = V.toList xs
vec :: [Double] -> Vec
vec = Vec . V.fromList
fromInts :: [Int] -> Vec
fromInts xs = Vec . V.fromList . fmap fromIntegral $ xs
instance Additive Vec where
zero = Vec V.empty
(Vec xs) ⊕ (Vec ys)
| V.null xs = Vec ys
| V.null ys = Vec xs
| lx == ly = Vec (V.zipWith (+) xs ys)
| lx < ly = Vec (V.zipWith (+) xs (V.take lx ys) V.++ V.drop lx ys)
| ly < lx = Vec (V.zipWith (+) ys (V.take ly xs) V.++ V.drop ly xs)
where lx = V.length xs
ly = V.length ys
instance AdditiveGroup Vec where
addinv (Vec xs) = Vec (V.map negate xs)
instance RingModule Double Vec where
a ⊙ (Vec xs) = Vec (V.map (a *) xs)
instance RingModule Int Vec where
a ⊙ (Vec xs) = Vec (V.map (fromIntegral a *) xs)
innerProd :: Vec -> Vec -> Double
innerProd (Vec xs) (Vec ys) = V.sum (V.zipWith (*) xs ys)
showFVec :: Maybe Int -> Vec -> String
showFVec prec (Vec xs) = "[" ++ (unwords . fmap (\x -> showFFloat prec x []) . V.toList $ xs) ++ "]"
normVec :: Vec -> Double
normVec x = sqrt (innerProd x x)
l1Vec :: Vec -> Double
l1Vec (Vec xs) = V.sum (V.map abs xs)
dl1Vec :: Vec -> Vec
dl1Vec (Vec xs) = Vec (V.map signum xs)
normalizeVec :: Vec -> Vec
normalizeVec x = if n == 0 then x else (1/n) ⊙ x
where n = normVec x
consVec :: Double -> Vec -> Vec
consVec x (Vec xs) = Vec (V.cons x xs)