[Haskell-beginners] What am I reinventing here

Dániel Arató exitconsole at gmail.com
Tue Sep 16 21:11:02 UTC 2014


Hey guys,

I was working through 99 Haskell Problems a while back and while
refactoring my solution to Problem 9 I couldn't help feeling I was
reinventing something basic. My thinking was, this problem can be
generalized to letting a function recursively process arbitrary chunks
of a given data structure in several passes until the whole data is
consumed while some function is extracting some information in an
accumulator.

So I wrote a mini-typeclass like so:

class Exhaustible e where
    isEmpty :: e -> Bool
instance Exhaustible [a] where
    isEmpty = null

exhaust :: Exhaustible e => (e -> (b, e)) -> (a -> b -> a) -> a -> e -> a
exhaust f g z xs
    | isEmpty xs = z
    | otherwise  = let (val, rest) = f xs in
                   exhaust f g (g z val) rest

Now the solution to Problem 9 is easy to define in terms of "exhaust".

Then I thought, "Why am I treating empty as a special value again?",
and wrote this instead:

stabilize :: Eq a => (a -> (b, a)) -> (c -> b -> c) -> c -> a -> (c, a)
stabilize f g z d
    | d == d'   = (z', d')
    | otherwise = stabilize f g z' d'
     where (val, d') = f d
           z' = g z val

This looks both really useful and extremely basic to me, so I'm
wondering what the standard way to do the same thing might be. I
looked at Foldable + foldr but the idea there seems to be to process a
data structure _one_ element at a time.

So my question is, is there an official implementation for this
combinator I called "stabilize"? Also, any tips on improving the
definitions and comments on how situations like Problem 9 should be
approached are welcome.

Daniel


More information about the Beginners mailing list