packages feed

multipass-0.1: examples/Pass.hs

{-# LANGUAGE GADTs, DeriveDataTypeable, StandaloneDeriving, ExtendedDefaultRules, GeneralizedNewtypeDeriving #-}

import Control.Applicative
import Control.Category
import Control.Newtype
import Control.Monad (liftM)
import Data.Binary
import Data.Foldable
import Data.Hashable
import Data.IntMap (IntMap)
import qualified Data.IntMap as IntMap
import Data.Monoid
import Data.Typeable
import Data.Pass
import Data.Pass.Monoid.Ord
import Prelude hiding (id,(.))

-- example calculation type
data Test a b where
  Total    :: Num a => Test a (Sum a)
  Count    :: Test a (Sum Int)
  Square   :: Num a => Test a a
  Minus    :: Double -> Test Double Double
  Abs      :: Num a => Test a a
  Smallest :: Num a => Test a (Min a)
  Largest  :: Num a => Test a (Max a)
  deriving Typeable

deriving instance Typeable1 Sum -- :(
deriving instance Binary a => Binary (Sum a)

count :: (Step t, Num b) => t Test a b
count = step $ fromIntegral . getSum <$> trans Count

sumSq :: Step t => t Test Double Double
sumSq = step $ Square `prep` total

-- | @E[X^2] - E[X]^2@
var :: Step t => t Test Double Double
var = step $ sumSq / count - mean ^ 2

stddev :: Step t => t Test Double Double
stddev = step $ sqrt var

-- > absDev median -- median absolute deviation
-- > absDev mean   -- mean absolute deviation
absdev :: Pass Test Double Double -> Calc Test Double Double
absdev mu = mu :& \m -> Minus m `prep` Abs `prep` step mu

-- median absolute deviation
mad :: Calc Test Double Double
mad = absdev median

instance Named Test where
  showsFun _ Total     = showString "Total"
  showsFun _ Count     = showString "Count"
  showsFun _ Square    = showString "Square"
  showsFun d (Minus n) = showParen (d > 10) $ showString "Minus " . showsPrec 10 n
  showsFun _ Abs       = showString "Abs"
  showsFun _ Largest   = showString "Largest"
  showsFun _ Smallest  = showString "Smallest"

instance Call Test where
  call Total a = Sum a
  call Count _ = Sum 1
  call Square a = a * a
  call (Minus n) a = a - n
  call Abs a = abs a
  call Largest a = Max a
  call Smallest a = Min a

instance Accelerant Test where
  meanPass  = total / count
  totalPass = getSum <$> trans Total
  largestPass = getMax <$> trans Largest
  smallestPass = getMin <$> trans Smallest

infixl 0 @!

(@!) :: Calc Test a b -> [a] -> b
(@!) = (@@)