I'm dealing with data that stores its state as a
String, treating the string like a stack. I also have to combine that with error handling.
To that end, I'm using the type
StateT String Maybe a. I have a function to pop and to push a
Char from and to the string:
pop :: StateT String Maybe Char pop = do x:xs <- get put xs return x push :: Char -> StateT String Maybe () push x = do xs <- get put (x:xs) return ()
I wrote a function to repeatedly
pop from the string while the characters being popped fulfilled a condition. It behaves as follows:
> runStateT (popWhile (<'a')) "HELLO world" Just ("HELLO ","world") > runStateT (popWhile (>'a')) "HELLO world" Just ("","HELLO world")
My implementation is the following:
popWhile :: (Char -> Bool) -> StateT String Maybe [Char] popWhile f = do s <- get if null s then return  else popAgain where popAgain = do x <- pop if f x then liftM (x:) (popWhile f) else push x >> return 
But that seems pretty bulky, and has two
if then else's in it. Is there a better way to write this function?