[Haskell-beginners] IO Problem

Daniel Fischer daniel.is.fischer at web.de
Fri Oct 17 09:40:46 EDT 2008

Am Freitag, 17. Oktober 2008 08:58 schrieb Jamie McCloskey:
> Hi everyone,
> I have just started learning Haskell, it is a very interesting language.
> As a first project, I am building a brainfuck interpreter, but have hit
> a stumbling block: IO. My program source is located at
> http://hpaste.org/11219
> My program handles the state of a brainfuck program by passing
> State(lists of ints) objects around. When I added my getIn fuction,
> however, it needed to return an IO State object. This broke the run
> function, as it returned a State. No problem, I thought, and changed run
> to return IO State. This broke my exec function, which calls run on each
> element in a list.
> As exec passes on the state returned by the run function to itself, it
> needs to take an IO State. This causes problems in the loop function,
> which calls exec on a subprogram. Because exec now takes IO State, loop
> also needs to. However, loop is called by run, so now run needs to take
> IO State. Now, all functions called by run need to take IO State.
> All this creates a whole load of functions with IO, even though it
> should not be necessary. What I would like to know, is how I can avoid
> this, possibly by modifying exec to just take a State.

exec [] st = return st
exec (x:xs) st = do
	newSt <- run x st
	exec xs newSt

exec (x:xs) st = run x st >>= exec xs

Once you're doing input or output, you're in IO, so run and exec must have 
type a -> b -> IO c, getIn and putOut must also live in IO, everything else 

> Whew! What a long-winded explanation!
> Any ideas?
> --Jamie
> P.S. Please ignore my long-winded list iteration functions -- I'm
> working on a cleaner version.

Probably the tidiest (as if that was a criterion for a brainfuck interpreter) 
would be to rename your State to ProgramState (or whatever) and write the 
interpreter in
StateT ProgramState IO
, you'd have
run :: Operator -> StateT ProgramState IO ()
run Add = modify myAdd
run Minus = ...
run Input = do
	n <- lift $ readLn
	modify (inHelper n)

exec = mapM_ run


More information about the Beginners mailing list