[Haskell-cafe] Re: [Haskell] Top Level <-

Ganesh Sittampalam ganesh at earth.li
Mon Sep 1 18:21:03 EDT 2008


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


More information about the Haskell-Cafe mailing list