1{-# LANGUAGE BangPatterns #-}
2
3module Text.EditDistance.MonadUtilities where
4
5{-# INLINE loopM_ #-}
6loopM_ :: Monad m => Int -> Int -> (Int -> m ()) -> m ()
7loopM_ xfrom xto action = go xfrom xto
8  where
9    go from to | from > to = return ()
10               | otherwise = do action from
11                                go (from + 1) to
12
13-- foldM in Control.Monad is not defined using SAT style so optimises very poorly
14{-# INLINE foldM #-}
15foldM             :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
16foldM f x xs = foldr (\y rest a -> f a y >>= rest) return xs x
17{-
18-- If we define it like this, then we aren't able to deforest wrt. a "build" in xs, which would be sad :(
19foldM f = go
20  where go a (x:xs)  =  f a x >>= \fax -> go fax xs
21        go a []      =  return a
22-}
23
24-- If we just use a standard foldM then our loops often box stuff up to return from the loop which is then immediately discarded
25-- TODO: using this instead of foldM improves our benchmarks by about 2% but makes the code quite ugly.. figure out what to do
26{-# INLINE foldMK #-}
27foldMK             :: (Monad m) => (a -> b -> m a) -> a -> [b] -> (a -> m res) -> m res
28foldMK f x xs k = foldr (\y rest a -> f a y >>= rest) k xs x
29