Counting occurrences of Char8s in a file
If you're using "Char8", then it would make a lot of sense to me to write a simple histogram type function using a mutable attay in the ST monad, and then calculate the minimum and maximum values at the end; there's no need to do it as you go.

import Data.Vector.Unboxed.Mutable as V
import Data.Vector.Unboxed as V
import Data.ByteString as B
import Control.Monad.ST
import Data.Char

histo :: B.ByteString -&gt; (Int,Int,Int)
histo bs = 
    let vec = create ( do
                mvec &lt;- V.replicate 256 0
                forM [0 .. B.length bs - 1] $ \i -&gt; do
                    let c = fromIntegral (B.index i bs) :: Int
                    n &lt;- unsafeRead mvec c
                    unsafeWrite mvec c (n+1)
                return mvec
                )
        f :: (Int, Int, Int) -&gt; Int -&gt; Word8 -&gt; (Int, Int, Int)
        f (mn,mx,cnt) i w =
            let mn'  = if w &gt; 0 &amp;&amp; w &lt; unsafeIndex vec mn then i else mn
                mx'  = if          w &gt; unsafeIndex vec mx then i else mx
                cnt' = if isPrint (chr . fromIntegral $ w) then cnt+1 else cnt
            in (mn', mx',cnt')

     in V.foldl' f (32, 32,0) vec -- 32 = index for ' '


This should calculate the result in constant memory (though the fold should probably be made more strict using a strict 3-tuple but all three values are forced each time f is called anyway). I haven't tested this code because I don't currently have access to a compiler so there are probably missing imports and some type errors but I hope the gist is clear.

I think this is a good demonstration of when some mutation is useful (counting lots of elements) and when functional algorithms are clearer (folding over all the data). The counting could have been done using a fold too but I think it's easier to see that here it is definitely using a constant amount of memory for the counts and should also perform quite well.