combinat-0.2.8.1: Math/Combinat/Sign.hs
-- | Signs
{-# LANGUAGE BangPatterns #-}
module Math.Combinat.Sign where
--------------------------------------------------------------------------------
import Data.Monoid
import System.Random
--------------------------------------------------------------------------------
data Sign
= Plus -- hmm, this way @Plus < Minus@, not sure about that
| Minus
deriving (Eq,Ord,Show,Read)
instance Monoid Sign where
mempty = Plus
mappend = mulSign
mconcat = productOfSigns
instance Random Sign where
random g = let (b,g') = random g in (if b then Plus else Minus, g')
randomR (u,v) g = let (y,g') = random g in (if u==v then u else y , g')
isPlus, isMinus :: Sign -> Bool
isPlus s = case s of { Plus -> True ; _ -> False }
isMinus s = case s of { Minus -> True ; _ -> False }
-- | @+1@ or @-1@
signValue :: Num a => Sign -> a
signValue s = case s of
Plus -> 1
Minus -> -1
-- | 'Plus' if even, 'Minus' if odd
paritySign :: Integral a => a -> Sign
paritySign x = if even x then Plus else Minus
oppositeSign :: Sign -> Sign
oppositeSign s = case s of
Plus -> Minus
Minus -> Plus
mulSign :: Sign -> Sign -> Sign
mulSign s1 s2 = case s1 of
Plus -> s2
Minus -> oppositeSign s2
productOfSigns :: [Sign] -> Sign
productOfSigns = go Plus where
go !acc [] = acc
go !acc (x:xs) = case x of
Plus -> go acc xs
Minus -> go (oppositeSign acc) xs
--------------------------------------------------------------------------------