IO behaves oddly if used nested

Alastair Reid alastair at
Fri Oct 3 11:00:41 EDT 2003

> I think it's wrong.  The return type of IO should be discarded.

I don't follow.  I thought the question was 'what should this print?' not 
'what is its type?'

> Even if it isn't, it doesn't make sense for IO to be in Show.

The general policy for Haskell 98 libraries is that if you define a type, you 
should define a Show instance even if it isn't possible to provide much 
information.  Thus, we have Show instances for -> and IO and, in the Haskell 
extension libraries, we have Show instances for IORef, MVar, etc.

It's a bit of a delicate balance.

On the one hand, it lets us derive or write a Show instance for any new type 
constructor that the user might define or any type that might occur in their 
program.  This makes teaching and some forms of debugging easier.

On the other hand, if you're not using it for debugging purposes, you might 
like the typechecker to detect that you're doing something silly just as it 
would if you wrote 'foo == (\x -> x)' or 'sin "1"'.  But it isn't quite as 
bad as equality on functions would be since such a test would either fail to 
terminate in many cases or would have to return an incorrect answer.  

Overall, I think the balance is about right.  Providing Show instances for IO 
doesn't lead to runtime problems and it doesn't break the desirable 'read . 
show = id' property since there is no Read instance. 

Of course, it might be nice if people could choose for themselves whether they 
get Show instances for IO and ->.  The simplest way to do this would be to 
not provide instances in Prelude and have them explicitly import the module 
if they need it.  Haskell compilers could perhaps implicitly import this 
module if the compiler is in 'Haskell 98' mode.

Alastair Reid

More information about the Haskell mailing list