Just for the record, the standard proof of the undecideability of the halting problem relies on the same idea as quines: that it's possible to write a program some sub-term of which evaluates to the source code for the whole program. Then, if there was a function halts
that, given source code for a program, returned True if that program halted on all input and False otherwise, this would be a legal program:
prog() = if halts "prog" then prog() else ()
where "prog"
would be some expression that evaluated to the source code for prog
; however, you can quickly see that prog
halts (for all inputs) iff it doesn't halt, which is a contradiction. Nothing in this proof relies on I/O in any way (do you need I/O to write a quine?).
By the way, you might want to look in to "dialog-based I/O" for further evidence that I/O is entirely irrelevant to your problem (basically, programs that do I/O can be reduced to programs that take input as (explicit) functional arguments and return output as (explicit) additional results in a lazy language). Unfortunately, I can't find a reasonable, un-biased (or pro-dialog) page on the web right now.