praxis

Various programming exercises.
git clone git://git.jtobin.io/praxis.git
Log | Files | Refs

Entropy.hs (1034B)


      1 {-# OPTIONS_GHC -Wall #-}
      2 {-# OPTIONS_GHC -fno-warn-type-defaults #-}
      3 {-# OPTIONS_GHC -fno-warn-unused-binds #-}
      4 
      5 import           Control.Foldl    (Fold (..))
      6 import qualified Control.Foldl    as L
      7 import           Data.Map.Strict  (Map)
      8 import qualified Data.Map.Strict  as Map
      9 import           Pipes            ((>->))
     10 import qualified Pipes.ByteString as P
     11 
     12 group :: (Ord k, Num a) => Fold k (Map k a)
     13 group = Fold step mempty id where
     14   step m k = Map.insertWith (+) k 1 m
     15 
     16 distribution :: (Ord k, Fractional a) => Fold k (Map k a)
     17 distribution = divide <$> group <*> L.genericLength where
     18   divide m n = fmap (/ n) m
     19 
     20 entropize :: Floating a => a -> a
     21 entropize m = negate (m * logBase 2 m)
     22 
     23 entropy :: (Foldable f, Ord k, Floating a) => f k -> a
     24 entropy = L.fold (L.premap entropize L.sum) . L.fold distribution
     25 
     26 main :: IO ()
     27 main = do
     28   let source = P.stdin >-> P.filter (/= 10)
     29   dist <- case distribution of
     30     Fold step start extract -> P.foldBytes step start extract source
     31   print $ L.fold L.sum (fmap entropize dist)
     32