Naive Bayes classifier

I needed to put together a Bayes classifier quickly to test an idea and did not want to pull in anything large from Hackage. If you ever find yourself in the same situation, here is the code:

Haskell
module Bayes where
 
import Data.Map.Strict (Map(..), (!), elems)
 
newtype Classifier c s = Classifier { getClass :: Map c [s] }
 
count :: Eq a => a -> [a] -> Int
count y = foldl (\acc x -> if y == x then acc + 1 else acc) 0
 
classSize :: Ord c => Classifier c s -> c -> Int
classSize cl = length . (getClass cl !)
 
totalSize :: Classifier c s -> Int
totalSize = length . concat . elems . getClass
 
sampleCount :: Eq s => Classifier c s -> s -> Int
sampleCount cl s = count s . concat . elems . getClass $ cl
 
sampleCountInClass :: (Ord c, Eq s) => Classifier c s -> s -> c -> Int
sampleCountInClass cl s = count s . (getClass cl !)
 
-- P(C)
prior :: Ord c => Classifier c s -> c -> Double
prior cl c = if tot == 0 then 0 else tr / fromIntegral tot
  where tr = fromIntegral $ classSize cl c
        tot = totalSize cl
 
-- P(D|C)
likelihood :: (Ord c, Eq s) => Classifier c s -> s -> c -> Double
likelihood cl s c = if tr == 0 then 0 else ss / fromIntegral tr
  where ss = fromIntegral $ sampleCountInClass cl s c
        tr = classSize cl c
 
-- P (D)
evidance :: Eq s => Classifier c s -> s -> Double
evidance cl s = if tot == 0 then 0 else sam / fromIntegral tot
  where sam = fromIntegral $ sampleCount cl s
        tot = totalSize cl
 
-- P(C|D) = P(D|C) * P(C) / P(D)
posterior :: (Ord c, Eq s) => Classifier c s -> c -> s -> Double
posterior cl c s = l * p / e
  where p = prior cl c
        l = likelihood cl s c
        e = evidance cl s
 
-- ln $ P(C|D) / P(not-C|D)
logLike :: (Ord c, Eq s) => Classifier c s -> c -> s -> Double
logLike cl c s = log $ p / (1 - p)
  where p = posterior cl c s
↑↓ navigate ↵ open esc close