Refactoring a Telnet parser
I think one of the reason why functional programming is usually easier is its natural modularity. Consider to design your solution in a more layered way. I.e. separate parser and invocations. Avoid callbacks in favor of lazy stream of events (see unsafeInterleaveIO) or borrow ideas from reactive frameworks. Also see Data.Binary.Get module or parsec package for implementing parser.