[Haskell-cafe] Current situation regarding global IORefs
ahey at iee.org
Sat Apr 29 06:05:22 EDT 2006
Lennart Augustsson wrote:
> Adrian Hey wrote:
>> Or put another way, would it be possible to implement the socket
>> API, exactly as it currently is, entirely in Haskell, starting with
>> nothing but hardware? I don't believe it is possible, but perhaps
>> somebody can show me I'm wrong.
> If I get to implement the IO monad, sure. :)
Perhaps you could give some indication of what you have in mind?
AFAICS the problem, if it is a problem, is a semantic problem
that afflicts all IO monad implementations. What would be different
about your implementation?
>> IME, the approach you take to these kinds of problems can vary
>> depending what you know or don't know for certain about the
>> system your working with. But you always end up using top level
>> mutable state somewhere along the way. I can only assume folk who
>> insist it's unnecessary (or worse) have never actually tried
>> implementing an IO sub-system from the ground up, starting with
>> nothing but bare hardware.
> I've written about 50000 lines of USB devices drivers for *BSD (in C).
> They work from the bare metal and up. They contain no global
> mutable state (except for variables that define debugging levels,
> because you need to access these from the in-kernel debugger).
Yes, I was aware of this. But with all due respect, if you're running
with an OS already present (not what I would call bare metal :-), your
device driver alone is not the entire IO sub-system. I'm not sure
what you mean by it having no mutable state. Do you mean no top level
mutable state, or do you mean there is no mutable state whatsoever
associated with a particular USB port(device..whatever)?
I assume you mean the former, and that the mutable device state
itself is passed as a parameter to your code, some how. If so I think
this is fine and good practice (even my noddy device driver on the
wiki does this).
But it seems to me when you consider the system as whole, the real
problem is the creation, management and aquisition of the device
states (state handles) by software that uses particular devices.
I'll try to keep this brief, maybe you or someone else can explain
the flaw in my logic, if there is one..
Consider a bit of code in the IO monad that needs a device handle
to perform some IO action with the corresponding device. How
does it acquire this handle? I can think of 3 ways..
1- It receives it as an argument. No problem, except when I
look at the Haskell libraries most of them don't seem to be
taking such arguments (main takes none whatsoever).
2- It creates it locally with some kind of newDeviceState
constructor. Well there might be some particularly privileged
bit of code somewhere in the system that is allowed to do
this, but clearly this isn't an option for most code.
3- It gets from some other data structure which is accessible
at the top level. IOW a "global variable". This doesn't
seem to be an option either in a language that has been
designed to prevent the creation of such things.
Unless I'm missing something, there seems to be a very serious
problem somewhere. If so, it should be fixed IMO, one way or
Now as JM mentioned, the reason nobody seems to notice this problem
is that in reality folk *are* relying on "global variables" somewhere
in the system. But they're buried so deeply in unsafePerformIO
hacked Haskell libraries, C libraries and OS internals that nobody
notices. They're just accepted as being part of "the world".
So when people say things like "I have never ever had to use a
global variable", I'm inclined to believe them. But I also say that
the only reason they can claim to be without "sin" is because
somebody else has already sinned on their behalf to provide them
with the IO libraries they use.
More information about the Haskell-Cafe