step :: Corpus -> Probs -> Probs
step corpus probs = {-# SCC "step"#-} HM.mapWithKey (\k@(_,f) _ -> val k f) $ probs
  where val k f = (/) ((HM.!) counts k) ((HM.!) totals f)
        (counts,totals) = foldl counter (HM.empty, HM.empty) corpus
        counter = foldPair inserter
        inserter k x y ac = (insertCount k x y ac, insertTotal k x y ac)
        insertCount k x y ac =  HM.insertWith
                                       (+) -- operation
                                       (x,y) -- key
                                       (((HM.!) probs (x,y)) / ((HM.!) (normalization k) x)) -- value to add
                                       $ fst ac -- map
        insertTotal k x y ac =  HM.insertWith
                                       (+)
                                       y
                                       (((HM.!) probs (x,y)) / ((HM.!) (normalization k) x))
                                       $ snd ac
        normalization  = foldPair (\_ x y acc -> HM.insertWith (+) x ((HM.!) probs (x,y)) acc) HM.empty
step :: Corpus -> Probs -> Probs
step corpus probs = {-# SCC "step"#-} HM.mapWithKey (\k@(_,f) _ -> val k f) $ probs
  where val k f = (/) ((HM.!) counts k) ((HM.!) totals f)
        (counts,totals) = foldl counter (HM.empty, HM.empty) corpus
        counter = foldPair inserter
        inserter k x y ac = (insertCount k x y ac, insertTotal k x y ac)
        insertCount k x y ac =  HM.insertWith
                                       (+) -- operation
                                       (x,y) -- key
                                       (((HM.!) probs (x,y)) / ((HM.!) (normalization k) x)) -- value to add
                                       $ fst ac -- map
        insertTotal k x y ac =  HM.insertWith
                                       (+)
                                       y
                                       (((HM.!) probs (x,y)) / ((HM.!) (normalization k) x))
                                       $ snd ac
        normalization  = foldPair (\_ x y acc -> HM.insertWith (+) x ((HM.!) probs (x,y)) acc) HM.empty
step corpus probs = {-# SCC "step"#-} HM.mapWithKey (\k@(_,f) _ -> val k f) $ probs
  where val k f = (/) ((HM.!) counts k) ((HM.!) totals f)
        (counts,totals) = foldl counter (HM.empty, HM.empty) corpus
        counter = foldPair inserter
        inserter k x y ac = (insertCount k x y ac, insertTotal k x y ac)
        insertCount k x y ac =  HM.insertWith
                                       (+) -- operation
                                       (x,y) -- key
                                       (((HM.!) probs (x,y)) / ((HM.!) (normalization k) x)) -- value to add
                                       $ fst ac -- map
        insertTotal k x y ac =  HM.insertWith
                                       (+)
                                       y
                                       (((HM.!) probs (x,y)) / ((HM.!) (normalization k) x))
                                       $ snd ac
        normalization  = foldPair (\_ x y acc -> HM.insertWith (+) x ((HM.!) probs (x,y)) acc) HM.empty