packages feed

monoid-statistics (empty) → 0.1

raw patch · 4 files changed

+245/−0 lines, 4 filesdep +basesetup-changed

Dependencies added: base

Files

+ Data/Monoid/Statistics.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances     #-}+{-# LANGUAGE BangPatterns          #-}+-- |+-- Module     : Data.Monoid.Statistics+-- Copyright  : Copyright (c) 2010, Alexey Khudyakov <alexey.skladnoy@gmail.com>+-- License    : BSD3+-- Maintainer : Alexey Khudyakov <alexey.skladnoy@gmail.com>+-- Stability  : experimental+-- +module Data.Monoid.Statistics ( StatMonoid(..)+                              , evalStatistic+                                -- * Statistic monoids+                              , Count(..)+                              , Mean(..)+                                -- * Additional information+                                -- $info+                              ) where+++import Data.Int     (Int8, Int16, Int32, Int64)+import Data.Word    (Word8,Word16,Word32,Word64,Word)+import Data.Monoid+import qualified Data.Foldable as F++import GHC.Float (float2Double)++-- | Monoid which corresponds to some stattics. In order to do so it+--   must be commutative. In many cases it's not practical to+--   construct monoids for each element so 'papennd' was added.+--   First parameter of type class is monoidal accumulator. Second is+--   type of element over which statistic is calculated. +--+--   Statistic could be calculated with fold over sample. Since+--   accumulator is 'Monoid' such fold could be easily parralelized.+--+--   Instance must satisfy following law:+--+--   > pappend x (pappend y mempty) == pappend x mempty `mappend` pappend y mempty+--   > mappend x y == mappend y x+class Monoid m => StatMonoid m a where+  -- | Add one element to monoid accumulator. P stands for point in+  --   analogy for Pointed.+  pappend :: a -> m -> m++-- | Calculate statistic over 'Foldable'. It's implemented in terms of+--   foldl'.+evalStatistic :: (F.Foldable d, StatMonoid m a) => d a -> m+evalStatistic = F.foldl' (flip pappend) mempty+++----------------------------------------------------------------+-- Data types+----------------------------------------------------------------++-- | Simplest statistics. Number of elements in the sample+newtype Count a = Count { calcCount :: a }+                  deriving Show++instance Integral a => Monoid (Count a) where+  mempty = Count 0+  (Count i) `mappend` (Count j) = Count (i + j)+  {-# INLINE mempty  #-}+  {-# INLINE mappend #-}+  +instance (Integral a) => StatMonoid (Count a) b where+  pappend _ !(Count n) = Count (n + 1)+  {-# INLINE pappend #-}+  +  +  +-- | Mean of sample. Samples of Double,Float and bui;t-in integral+--   types are supported+--+-- Numeric stability of 'mappend' is not proven.+data Mean = Mean { calcMean      :: Double -- ^ Current mean+                 , calcCountMean :: Int    -- ^ Number of entries+                 }+            deriving Show++instance Monoid Mean where+  mempty = Mean 0 0+  mappend !(Mean x n) !(Mean y k) = Mean ((x*n' + y*k') / (n' + k')) (n + k)+    where+      n' = fromIntegral n+      k' = fromIntegral k+  {-# INLINE mempty  #-}+  {-# INLINE mappend #-}++-- Add one sample elemnt to Mean+addValueToMean :: (a -> Double) -> a -> Mean -> Mean+addValueToMean f !x !(Mean m n) = Mean (m + (f x - m) / fromIntegral n') n' where n' = n+1+{-# INLINE addValueToMean #-}++-- Floating point+instance StatMonoid Mean Double where+  pappend = addValueToMean id+  {-# INLINE pappend #-}+instance StatMonoid Mean Float where+  pappend = addValueToMean float2Double+  {-# INLINE pappend #-}++-- Basic integrals+instance StatMonoid Mean Integer where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+instance StatMonoid Mean Int where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+instance StatMonoid Mean Word where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}++-- Fixed size ints+instance StatMonoid Mean Int8 where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+instance StatMonoid Mean Int16 where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+instance StatMonoid Mean Int32 where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+instance StatMonoid Mean Int64 where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}++-- Fixed size Words+instance StatMonoid Mean Word8 where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+instance StatMonoid Mean Word16 where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+instance StatMonoid Mean Word32 where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+instance StatMonoid Mean Word64 where+  pappend = addValueToMean fromIntegral+  {-# INLINE pappend #-}+++----------------------------------------------------------------+-- Generic monoids+----------------------------------------------------------------++-- | Monoid which allows to calculate two statistics in parralel+data TwoStats a b = TwoStats { calcStat1 :: a+                             , calcStat2 :: b+                             }++instance (Monoid a, Monoid b) => Monoid (TwoStats a b) where+  mempty = TwoStats mempty mempty+  mappend !(TwoStats x y) !(TwoStats x' y') = +    TwoStats (mappend x x') (mappend y y')+  {-# INLINE mempty  #-}+  {-# INLINE mappend #-}++instance (StatMonoid a x, StatMonoid b x) => StatMonoid (TwoStats a b) x where+  pappend !x !(TwoStats a b) = TwoStats (pappend x a) (pappend x b)+  {-# INLINE pappend #-}++            +-- $info+--+-- Statistic is function of a sample which does not depend on order of+-- elements in a sample. For each statistics corresponding monoid+-- could be constructed:+--+-- > f :: [A] -> B+-- >+-- > data F = F [A]+-- >+-- > evalF (F xs) = f xs+-- >+-- > instance Monoid F here+-- >   mempty = F []+-- >   (F a) `mappend` (F b) = F (a ++ b)+--+-- This indeed proves that monoid could be constructed. Monoid above+-- is completely impractical. It runs in O(n) space. However for some+-- statistics monoids which runs in O(1) space could be+-- implemented. For example mean. +--+-- On the other hand some statistics could not be implemented in such+-- way. For example calculation of median require O(n) space. Variance+-- could be implemented in O(1) but such implementation won't be+-- numerically stable. 
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) Alexey Khudyakov++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ monoid-statistics.cabal view
@@ -0,0 +1,25 @@+Name:           monoid-statistics+Version:        0.1+Cabal-Version:  >= 1.6+License:        BSD3+License-File:   LICENSE+Author:         Alexey Khudyakov <alexey.skladnoy@gmail.com>+Maintainer:     Alexey Khudyakov <alexey.skladnoy@gmail.com>+Homepage:       https://bitbucket.org/Shimuuar/monoid-statistics+Category:       Statistics+Build-Type:     Simple+Synopsis:       +  Monoids for calculation of statistics of sample+Description:+  Monoids for calculation of statistics of sample+  .+  Currently only mean and number of elements could be calculated+++source-repository head+  type:     hg+  location: http://bitbucket.org/Shimuuar/monoid-statistics++Library+  Build-Depends:   base >=3 && <5+  Exposed-modules: Data.Monoid.Statistics