On Mon, 1 Sep 2008, Adrian Hey wrote:

Ganesh Sittampalam wrote:
On Sun, 31 Aug 2008, Adrian Hey wrote:
Eh? Please illustrate your point with Data.Unique. What requirements
does it place on it's context? (whatever that might mean :-)

It requires that its context initialises it precisely once.

It's context being main? If so this is true, but I don't see why this
is  a problem. [...]  Also ACIO monad properties guarantee that it's
always initialised to the same value regardless of when this occurs.
So I don't see the problem.

You see this as a requirement that can be discharged by adding the ACIO concept; I see it as a requirement that should be communicated in the type.

Another way of looking at it is that Data.Unique has associated with it some context in which Unique values are safely comparable. You want that context to always be the top-level/RTS scope, I would like the defining that context to be part of the API.

Data.Unique is actually a poor example, as it is actually fine to initialise it multiple times as long as the resulting Unique values aren't treated as coming from the same datatype.

I just don't see what you're getting at. There's no problem here
and Data.Unique is not special.

See the conversation with Ashley - you can have multiple copies of Data.Unique loaded without problem, as long as the resulting Unique datatypes aren't comparable with each other.

myCount :: MVar Int
myCount <- newMVar 0

In a hypothetical second initialisation, do you mean..
1 - myCount somehow gets rebound to a different/new MVar

I mean this. Or, more precisely, that a *different* myCount gets bound to a different MVar.

But equally it can be implemented with IORefs,

Actually it couldn't as IORefs are not an Ord instance.

Well, perhaps one could be added (along with hashing). Or perhaps it's not really needed; I don't know as I've never used Data.Unique, and I doubt I ever would as when I need a name supply I also want human readable names, and I can't think of any other uses for it, though no doubt some exist.

so it's not a good advert for the need for global variables.

Oh please!

We have to have something concrete to discuss and this is the simplest.
Like I said there are a dozen or so other examples in the base package
last time I counted

Would you mind listing them? It might help provide some clarity to the discussion.

and plenty of people have found that other libs/ffi bindings need them for safety reasons. Or at least they need something that has "global" main/process scope and so far the unsafePerformIO hack is the only known way to get that and still keep APIs stable,sane and modular.

Again, some specific examples would help.

Also, AFAICS going the way that seems to be suggested of having all this
stuff reflected in the arguments/types of API is going to make it
practically impossible to have platform independent APIs if all platform
specific implementation detail has to be accounted for in this way.

It can all be wrapped up in a single abstract context argument; the only platform "bleed" would be if one platform needed a context argument but others didn't.

I think there are two cases to consider here.

A Data.Unique style library, which requires genuinely *internal* state, and which is agnostic to having multiple copies of itself loaded simultaneously. In that case, there is no requirement for a process-level scope for <-, just that each instance of the library is only initialised once - the RTS can do this, as can any dynamic loader.

The other is some library that really cannot be safely loaded multiple times, because it depends on some lower-level shared resource. Such a library simply cannot be made safe without cooperation from the thing that controls that shared resource, because you cannot prevent a second copy of it being loaded by something you have no control over.

If the <- proposal were only about supporting the first of these applications, I would have far fewer objections to it. But it would have nothing to do with process-level scope, then.

The <- proposal introduces no new problems that aren't already with us.
It solves 1 problem in that at least there's no room for the compiler to
get it wrong or for people do use "dangerous things" when using the
unsafePerformIO hack. I think that is really the only problem that can
be solved at the level of Haskell language definition.

I just want to be clear that the second of the two categories above cannot be used to justify the proposal, as it does not make them safe.

I also think we need to be careful about the use of the term "process".

IMO when we say the "process" defined by main, we are talking about an
abstract process that is essentially defined by Haskell and may have
nothing in common with a "process" as defined by various OS's (assuming
there's an OS involved at all). Perhaps we should try be more clear and
say "Haskell process" or "OS process" as appropriate. In particular
when we say an MVar or IORef has "global" process scope (whether or
not it occurs at top level) we are talking about a Haskell process,
not an OS process.

We could call it "Haskell RTS scope" if you like; the term "Haskell process" is meaningless to me. Top-level scope, as defined in the emails between Ashley and myself, is also ok.

The issues you raise seem to me to be more to do with correct
implementaton on various platforms using various tools of varying
degrees of brokeness.

No, it's about correct implementation with different models of dynamic loading. None of the possibilities I am envisaging are broken, per se,
though they might well break the <- proposal.

But this problem is going to be with us whether or not top level <-
bindings are implemented (If they're not implemented people will
still be doing the same thing with the unsafePerformIO hack).

But then it will be easier to point to their libraries as being at fault when something goes wrong.

Ganesh
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to