
For a number of years, I've been hacking on a Z80 processor simulator, on and off. It's generally pure code that resembles and uses State, et. al. The design issue I've run into is adding devices to the memory system, unsurprisingly typed as MemorySystem. Devices like to do I/O, which potentially "pollutes" a design with Monads. So... I'm soliciting suggestions that allow me to isolate Monadic code in the middle of pure code (which might be Quixotic, but I'll accept that risk.) MemorySystem uses interval maps containing memory regions, and a memory region can be a RAMRegion, ROMRegion or DeviceRegion. The abbreviated data declarations are: type MemRegionMap addrType wordType = IM.IntervalMap addrType (MemoryRegion addrType wordType) data MemorySystem addrType wordType where MSys :: { _regions :: MemRegionMap addrType wordType } -> MemorySystem addrType wordType data MemoryRegion addrType wordType where EmptyRegion :: MemoryRegion addrType wordType RAMRegion :: {- ... -} ROMRegion :: {- ... -} DevRegion :: {- ... -} RAMRegion-s and ROMRegion-s are unboxed vector containers, which makes reading and writing to them pure State code, i.e., the last two function arguments to the reading function are "MemorySystem ... -> (Vector wordType, MemorySystem ...)", viz: type MemReadN addrType wordType = (Vector wordType, MemorySystem addrType wordType) mReadN :: addrType -- ^ Starting address -> Int -- ^ Number of words to read -> MemorySystem addrType wordType -- ^ The memory system from which to read -> MemReadN addrType wordType Supporting DevRegion-s gets more complicated, because I/O is involved (we like consoles on our machines, yes, we do.) I'd like to keep the reader signature without unnecessarily injecting a Monad or Monad Transformer into MemoryRegion and MemorySystem, thereby keeping the Monad or transformer isolated in DevRegion. For example, an internal device reader function would have a signature similar to "... -> Device m devType -> (Vector wordType, m devType)" instead of "... -> Device m devType -> m (Vector WordType, devType)", where "m" is the Monad or transformer. I know, it's hard to jailbreak things out of a Monad, which may be answering my own question. However, it seems to me that this kind of problem occurs in real world Haskell, and I haven't encountered the real world solution. Ideas? -scooter