Ashley Yakeley | 25 Aug 01:08

Top Level <-

Is there any interest in implementing a top level "<-" to run monadic code?

Currently this sort of thing is done with unsafePerformIO and switching 
off inlining with some pragma. Indeed, the 'atomically' haddock actually 
advises doing this to declare top-level TVars. The same trick is used in 
the source of Data.Unique and System.Random. This is bad Haskell.

To avoid observation of effects, etc., we would need a new monad rather 
than IO. There would be equivalents of IO functions such as these:

   newIORef
   newMVar
   newTVarIO
   newUnique

I can think of two uses:

1. Global mutable state. For instance, here's the count variable for 
Data.Unique rewritten:

   uniqSource :: MVar Integer
   uniqSource <- newMVarTL 0

Isn't that much nicer?
<http://haskell.org/haskellwiki/Top_level_mutable_state>

2. Solving the expression problem using open witnesses, a recent 
hobby-horse of mine. For instance, here's a simple scheme for extensible 
exceptions using top-level "<-":

(Continue reading)

Duncan Coutts | 25 Aug 02:46
Gravatar

Re: [Haskell] Top Level <-

This topic came up in #haskell this evening...

On Sun, 2008-08-24 at 16:12 -0700, Ashley Yakeley wrote:
> 1. Global mutable state. For instance, here's the count variable for 
> Data.Unique rewritten:
> 
>    uniqSource :: MVar Integer
>    uniqSource <- newMVarTL 0
> 
> Isn't that much nicer?
> <http://haskell.org/haskellwiki/Top_level_mutable_state>

It's nicer syntax but it's still not true. There's still no such thing
as a global variable. There's always a scope.

In this case what scope are we looking for? Process scope? Only one
instance of uniqSource per process? If so, it's not right. We can link
in multiple copies of a package and thereby end up with multiple
instances (this really happens, it's not a far fetched scenario).
So uniqSource is a package-name/version scope mutable variable.

To get the right thing for the annoying C libs that have 'global' init
and finalise functions you need something else. Not actually process
scope, that's too wide. You need exactly the same scope as the system
linker is using, so that we get one variable per instance of the C
library linked into the process. Consider a process using several dlls
where each one links to a C lib that needs 'global' initialisation, we
must have exactly one 'global' var instance per dll in this case because
that's the linker namespace scope.

(Continue reading)

Ashley Yakeley | 25 Aug 04:34

Re: [Haskell] Top Level <-

Duncan Coutts wrote:
> This topic came up in #haskell this evening...
> 
> On Sun, 2008-08-24 at 16:12 -0700, Ashley Yakeley wrote:
>> 1. Global mutable state. For instance, here's the count variable for 
>> Data.Unique rewritten:
>>
>>    uniqSource :: MVar Integer
>>    uniqSource <- newMVarTL 0
>>
>> Isn't that much nicer?
>> <http://haskell.org/haskellwiki/Top_level_mutable_state>
> 
> It's nicer syntax but it's still not true. There's still no such thing
> as a global variable. There's always a scope.
> 
> In this case what scope are we looking for? Process scope? Only one
> instance of uniqSource per process?

It is actually process scope, I believe. But it's one instance of 
"base-3.0.2.0:Data.Unique.uniqSource" per process: we don't care if 
there's also a "base-4.0:Data.Unique.uniqSource". The reason we don't 
care in this case is that base-3.0.2.0:Data.Unique.Unique and 
base-4.0:Data.Unique.Unique are different types, so they can't collide. 
These are different names in the same scope.

The scope I'm interested in is "Main.main" scope, i.e., the initialiser 
should be run no more than once per run of "main".

--

-- 
(Continue reading)

Edward Kmett | 25 Aug 16:43

Re: Top Level <-

On Sun, Aug 24, 2008 at 7:12 PM, Ashley Yakeley <ashley <at> semantic.org> wrote:
Is there any interest in implementing a top level "<-" to run monadic code?
 
This is actually implemented in jhc. See the 'top level actions' section of http://repetae.net/computer/jhc/manual.html 
 
-Edward Kmett
 
_______________________________________________
Haskell mailing list
Haskell <at> haskell.org
http://www.haskell.org/mailman/listinfo/haskell
Adrian Hey | 25 Aug 17:55
Favicon

Re: [Haskell] Top Level <-

(Moving to Haskell cafe)

Edward Kmett wrote:
> On Sun, Aug 24, 2008 at 7:12 PM, Ashley Yakeley <ashley <at> semantic.org> wrote:
> 
>> Is there any interest in implementing a top level "<-" to run monadic code?
>>
> 
> This is actually implemented in jhc. See the 'top level actions' section of
> http://repetae.net/computer/jhc/manual.html

Gosh! I was always quite impressed by Johns determination to write a
Haskell compiler and by his self discipline in resisting the temptation
to fix everything that was wrong with Haskell and keep to standards :-)

I implemented my own ACIO monad a while ago (which is of course quite
useless without top level <- bindings) and it turned out that there
was quite a lot that could go in here.

The only problem seemed to be that some things that seemed perfectly
reasonable to create via ACIO had *IO* finalisers associated with them,
which didn't feel right to me. But if you think about how finalisers
get run I'm inclined to think we should insist that they are ACIO too.

Regards
--
Adrian Hey
John Meacham | 26 Aug 04:03
Favicon

Re: Re: [Haskell] Top Level <-

On Mon, Aug 25, 2008 at 04:55:05PM +0100, Adrian Hey wrote:
> (Moving to Haskell cafe)
>
> Edward Kmett wrote:
>> On Sun, Aug 24, 2008 at 7:12 PM, Ashley Yakeley <ashley <at> semantic.org> wrote:
>>
>>> Is there any interest in implementing a top level "<-" to run monadic code?
>>>
>>
>> This is actually implemented in jhc. See the 'top level actions' section of
>> http://repetae.net/computer/jhc/manual.html
>
> Gosh! I was always quite impressed by Johns determination to write a
> Haskell compiler and by his self discipline in resisting the temptation
> to fix everything that was wrong with Haskell and keep to standards :-)

Heh. :) I have not had much time recently to work on jhc. but I hope to
pick it up full steam soon. There have been a lot of strong contributers
in the community as well. (sigh. day job syndrome). 

> I implemented my own ACIO monad a while ago (which is of course quite
> useless without top level <- bindings) and it turned out that there
> was quite a lot that could go in here.

Yeah, I based my design on what I thought was the 'community consensus'
on how they should look the last time the discussion came up. (not
counting those that were adamantly opposed to the idea alltogether ;) )
I forgot who came up with the original ACIO idea, but I'd give them
props in the manual if they wish.

> The only problem seemed to be that some things that seemed perfectly
> reasonable to create via ACIO had *IO* finalisers associated with them,
> which didn't feel right to me. But if you think about how finalisers
> get run I'm inclined to think we should insist that they are ACIO too.

Yeah, this sounds like a great idea. there were a whole lot of issues
dealing with finalizers and concurrency, and restricting them in some
way similar to ACIO might be good... however, you want something a
little weaker than ACIO I think. it must satisfy the ACIO conditions,
but _may_ assume its argument (the item being collected) is never
referenced again. hence something like 'free' is okay which wouldn't be
if other references to the object exist. do you think that is 'formal'
enough of a description? seems clear enough if ACIO is well defined which I
think it is.

        John

--

-- 
John Meacham - ⑆repetae.net⑆john⑈
Ashley Yakeley | 26 Aug 06:52

Re: [Haskell] Top Level <-

John Meacham wrote:
> ... if ACIO is well defined which I think it is.

Affine: ma >> mb = mb

Central:
  do {a <- ma;b <- mb;return (a,b)} = do {b <- mb;a <- ma;return (a,b)}

...for some concept of "=".

Is this correct? Are there any other constraints?
Adrian Hey | 26 Aug 09:07
Favicon

Re: Re: [Haskell] Top Level <-

John Meacham wrote:
> I forgot who came up with the original ACIO idea, but I'd give them
> props in the manual if they wish.

I think this is based on Ian Starks message..
  http://www.haskell.org/pipermail/haskell-cafe/2004-November/007664.html

> Yeah, this sounds like a great idea. there were a whole lot of issues
> dealing with finalizers and concurrency, and restricting them in some
> way similar to ACIO might be good... however, you want something a
> little weaker than ACIO I think. it must satisfy the ACIO conditions,
> but _may_ assume its argument (the item being collected) is never
> referenced again. hence something like 'free' is okay which wouldn't be
> if other references to the object exist. do you think that is 'formal'
> enough of a description? seems clear enough if ACIO is well defined which I
> think it is.

Yes, now I cast my mind back that was something that was troubling me.
Clearly the one thing you're most likely to want to do in a finaliser
is free some external resource, which certainly wouldn't be ACIO
ordinarily. But as you say, giving sane semantics and type safety
to finalisers is very tricky indeed.

I can't help thinking that semantically finaliser execution should be
treated like some kind of external event handling, like an interrupt.
Not sure what that should be properly, but I think finalisers should
be the same.

But from a top level aThing <- someACIO point of view, if we're going to
say that it doesn't matter if someACIO is executed before main is
entered (possibly even at compile time) or on demand, then we clearly
don't want to observe any difference between the latter case and the
former (if aThing becomes garbage without ever being demanded).

Maybe it would be safest to just say anything with a finaliser can't be
created at the top level. We can always define an appropriate top level
"get" IO action using runOnce or whatever.

Regards
--
Adrian Hey
Judah Jacobson | 26 Aug 10:14

Re: Re: [Haskell] Top Level <-

On Tue, Aug 26, 2008 at 12:07 AM, Adrian Hey <ahey <at> iee.org> wrote:
>
>
> But from a top level aThing <- someACIO point of view, if we're going to
> say that it doesn't matter if someACIO is executed before main is
> entered (possibly even at compile time) or on demand, then we clearly
> don't want to observe any difference between the latter case and the
> former (if aThing becomes garbage without ever being demanded).
>
> Maybe it would be safest to just say anything with a finaliser can't be
> created at the top level. We can always define an appropriate top level
> "get" IO action using runOnce or whatever.

I've been wondering: is there any benefit to having top-level ACIO'd
<- instead of just using runOnce (or perhaps "oneshot") as the
primitive for everything?  For example:

oneshot uniqueRef :: IO (MVar Integer)
uniqueRef =< newMVar 0

It was also suggested in that wiki page:
http://haskell.org/haskellwiki/Top_level_mutable_state#Proposal_4:_Shared_on-demand_IO_actions_.28oneShots.29

Those proposals eliminate the need for creating an ACIO monad and
enforcing its axioms, since one-shot actions are executed in-line with
other I/O actions (rather than at some nebulous "before the program is
run" time).

So, in the context of top-level initializers, does ACIO offer
something beyond what oneshot provides on its own?  If not, I prefer
the latter since it seems like a much simpler solution.

Best,
-Judah
Ashley Yakeley | 26 Aug 12:15

Re: [Haskell] Top Level <-

Judah Jacobson wrote:
> I've been wondering: is there any benefit to having top-level ACIO'd
> <- instead of just using runOnce (or perhaps "oneshot") as the
> primitive for everything?

I don't think oneshots are very good for open witness declarations (such 
as the open exceptions I mentioned originally), since there are pure 
functions that do useful things with them.

Not sure about TVars either, which operate in the STM monad. Would you 
also need a oneshotSTM (or a class)?

--

-- 
Ashley Yakeley
Judah Jacobson | 26 Aug 22:16

Re: [Haskell] Top Level <-

On Tue, Aug 26, 2008 at 3:15 AM, Ashley Yakeley <ashley <at> semantic.org> wrote:
> Judah Jacobson wrote:
>>
>> I've been wondering: is there any benefit to having top-level ACIO'd
>> <- instead of just using runOnce (or perhaps "oneshot") as the
>> primitive for everything?
>
> I don't think oneshots are very good for open witness declarations (such as
> the open exceptions I mentioned originally), since there are pure functions
> that do useful things with them.

I think you're saying that you want to write "w <- newIOWitness" at
the top level, so that w can then be referenced in a pure function.
Fair enough.  But newIOWitness's implementation requires writeIORef
(or an equivalent), which is not ACIO, right?  I suppose you could
call unsafeIOToACIO, but if that function is used often it seems to
defeat the purpose of defining an ACIO monad in the first place.

> Not sure about TVars either, which operate in the STM monad. Would you also
> need a oneshotSTM (or a class)?

Interesting point; I think you can work around it, but it does make
the code a little more complicated.  For example:

oneshot uniqueVar :: IO (TVar Integer)
uniqueVar =< atomically $ newTVar 0 -- alternately, use newTVarIO

uniqueIntSTM :: IO (STM Integer)
uniqueIntSTM = uniqueVar >>= \v -> return $ do
    n <- readTVar v
    writeTVar v (n+1)
    return n

getUniqueInt :: IO Integer
getUniqueInt = uniqueIntSTM >>= atomically

-Judah
Ashley Yakeley | 27 Aug 00:07

Re: [Haskell] Top Level <-

Judah Jacobson wrote:
> I think you're saying that you want to write "w <- newIOWitness" at
> the top level, so that w can then be referenced in a pure function.
> Fair enough.  But newIOWitness's implementation requires writeIORef
> (or an equivalent), which is not ACIO, right?

newIOWitness is very like newUnique. In both cases, the internal
implementation updates an MVar to make them unique. Internally the
open-witness package would use unsafeIOtoACIO (just as it already uses
unsafeCoerce), but an exposed newIOWitnessACIO would be safe.

> oneshot uniqueVar :: IO (TVar Integer)
> uniqueVar =< atomically $ newTVar 0 -- alternately, use newTVarIO
> 
> uniqueIntSTM :: IO (STM Integer)
> uniqueIntSTM = uniqueVar >>= \v -> return $ do
>     n <- readTVar v
>     writeTVar v (n+1)
>     return n
> 
> getUniqueInt :: IO Integer
> getUniqueInt = uniqueIntSTM >>= atomically

This complicates the purpose of STM, which is to make composable STM
transactions. I would rather do this:

  uniqueVar :: TVar Integer
  uniqueVar <- newTVarACIO

  uniqueInt :: STM Integer
  uniqueInt = do
    n <- readTVar uniqueVar
    writeTVar uniqueVar (n+1)
    return n

AFAICT, one-shots are less powerful and just as complicated as an ACIO
monad.

--

-- 
Ashley Yakeley
John Meacham | 27 Aug 02:34
Favicon

Re: Re: [Haskell] Top Level <-

On Tue, Aug 26, 2008 at 01:14:34AM -0700, Judah Jacobson wrote:
> On Tue, Aug 26, 2008 at 12:07 AM, Adrian Hey <ahey <at> iee.org> wrote:
> >
> >
> > But from a top level aThing <- someACIO point of view, if we're going to
> > say that it doesn't matter if someACIO is executed before main is
> > entered (possibly even at compile time) or on demand, then we clearly
> > don't want to observe any difference between the latter case and the
> > former (if aThing becomes garbage without ever being demanded).
> >
> > Maybe it would be safest to just say anything with a finaliser can't be
> > created at the top level. We can always define an appropriate top level
> > "get" IO action using runOnce or whatever.
> 
> I've been wondering: is there any benefit to having top-level ACIO'd
> <- instead of just using runOnce (or perhaps "oneshot") as the
> primitive for everything?  For example:
> 
> oneshot uniqueRef :: IO (MVar Integer)
> uniqueRef =< newMVar 0
> 
> It was also suggested in that wiki page:
> http://haskell.org/haskellwiki/Top_level_mutable_state#Proposal_4:_Shared_on-demand_IO_actions_.28oneShots.29
> 
> Those proposals eliminate the need for creating an ACIO monad and
> enforcing its axioms, since one-shot actions are executed in-line with
> other I/O actions (rather than at some nebulous "before the program is
> run" time).

Actually, due to the definition of ACIO, there is no difference between
the two (for actions actually in ACIO). It was formulated to have this
property. both implementations (executing them before the program is
run, or on first call) and ways of thinking about things are valid and
will be indistinguishable for all proper ACIO actions.

note, you can implement oneshot IO actions on top of ACIO top level
actions, but not the reverse.

I think ACIO is cleaner overall, since we have a nice formal definition
of when ACIO actions are valid without having to invoke the more
complicated IO monad.

        John

--

-- 
John Meacham - ⑆repetae.net⑆john⑈
Adrian Hey | 27 Aug 15:15
Favicon

Re: Re: [Haskell] Top Level <-

Judah Jacobson wrote:
> I've been wondering: is there any benefit to having top-level ACIO'd
> <- instead of just using runOnce (or perhaps "oneshot") as the
> primitive for everything?  For example:
> 
> oneshot uniqueRef :: IO (MVar Integer)
> uniqueRef =< newMVar 0

I've been wondering about something like this too (in some way just have
a oneShot or runOnce and the *only* thing in ACIO as a magic primitive).

runOnce :: IO a -> ACIO (IO a)

It would certainly simplify the ACIO monad :-), but I'm not sure it's
really as flexible. Provided newMVar can be ACIO then this can be
implemented directly (doesn't need to be a primitive). But we can't
go the other way round (use runOnce to create genuine top level MVars
or channels say).

Does that matter? Probably not for monadic IO code. It's not a huge
inconvenience to write..

  do ...
     thing <- getThing
     foo thing

vs..
  do ...
     foo thing -- thing is at top level

But for top level non monadic code/expressions/data structures I can
see a certain convenience in having thing as top level identifier
if possible, which it often won't be anyway I guess for other
reasons (like it's creation and initialisation requires real IO).

So I don't have any particularly strong opinion either way. In
practice if thing (or getThing) is to be exported then it
would probably be prudent to assume creation and initialisation
might require real IO at some point in the future even if they
don't right now, so you'd export getThing (= return thing) anyway,
rather then have an exported thing dissappear from the API at some
point.

My 2p..

Regards
--
Adrian Hey
John Meacham | 27 Aug 16:13
Favicon

Re: Re: [Haskell] Top Level <-

I think a strong advantage of the straight up ACIO formulation (rather
than a one-shot IO based thing) is that it can be fully, correctly, and
safely be defined without referencing the IO monad or its interaction
with the IO monad at all. In practice, ACIO will be generally be used to
interact with IO code. But being able to formalize it completely
independently of the IO monad and all the IO monad entails is an
enticing posibility.

        John

--

-- 
John Meacham - ⑆repetae.net⑆john⑈
Ashley Yakeley | 26 Aug 12:02

Re: [Haskell] Top Level <-

Adrian Hey wrote:
> Maybe it would be safest to just say anything with a finaliser can't be
> created at the top level.

Do you have an example of something that is correctly ACIO to create, 
but has a problematic finaliser?

--

-- 
Ashley Yakeley
Adrian Hey | 27 Aug 13:56
Favicon

Re: [Haskell] Top Level <-

Ashley Yakeley wrote:
> Adrian Hey wrote:
>> Maybe it would be safest to just say anything with a finaliser can't be
>> created at the top level.
> 
> Do you have an example of something that is correctly ACIO to create, 
> but has a problematic finaliser?

Sorry for the delay in getting my attention. I've been looking at
my old ACIO code (which I've largely forgotten the details
of) and dug up the following snippet.

  -- * Weak pointers
  -- | All these functions require that finalisers (if any) are in the
  -- ACIO Monad.
  -- I'm not sure what such a finaliser can usefully do, but it can't be
  -- in the IO Monad and preserve ACIO Monad properties AFAICS.
  mkWeak,mkWeakPtr,mkWeakPair,addFinalizer,mkWeakIORef,

I must admit I can't remember much about any of this, I just worked
my way through the IO libs trying to figure out which actions might
plausibly (if not usefully :-) be regarded as ACIO. There seemed to be
quite a lot at the end of the day.

I also added a few forkIO variants which force the forked thread
to block on certain things (empty MVar,Chan, QSem..) waiting for
some IO monad action to kick them into life.

Regards
--
Adrian Hey
John Meacham | 27 Aug 02:39
Favicon

Re: Re: [Haskell] Top Level <-

On Tue, Aug 26, 2008 at 08:07:24AM +0100, Adrian Hey wrote:
> But from a top level aThing <- someACIO point of view, if we're going to
> say that it doesn't matter if someACIO is executed before main is
> entered (possibly even at compile time) or on demand, then we clearly
> don't want to observe any difference between the latter case and the
> former (if aThing becomes garbage without ever being demanded).
>
> Maybe it would be safest to just say anything with a finaliser can't be
> created at the top level. We can always define an appropriate top level
> "get" IO action using runOnce or whatever.

If the finalizer is also in the weaker form of ACIO (ACIO under the no
more references exist to its argument presumption, maybe called
'linearity condition' or something?), then it shouldn't matter at all. I
can't think of any finalizers that don't obey this property that wern't
problematic under the old model to begin with.

        John

--

-- 
John Meacham - ⑆repetae.net⑆john⑈
Bulat Ziganshin | 26 Aug 17:01

Re: Top Level <-

Hello Ashley,

Monday, August 25, 2008, 3:12:18 AM, you wrote:

> Is there any interest in implementing a top level "<-" to run monadic code?

yes, definitely. as it's hard to develop "real" app w/o using global
vars, h98 still remains "unreal" language

but from my POV it's important to push this feature into haskell
standard

--

-- 
Best regards,
 Bulat                            mailto:Bulat.Ziganshin <at> gmail.com
Derek Elkins | 26 Aug 18:14

Re: Top Level <-

On Tue, 2008-08-26 at 19:01 +0400, Bulat Ziganshin wrote:
> Hello Ashley,
> 
> Monday, August 25, 2008, 3:12:18 AM, you wrote:
> 
> > Is there any interest in implementing a top level "<-" to run monadic code?
> 
> yes, definitely. as it's hard to develop "real" app w/o using global
> vars, h98 still remains "unreal" language
> 
> but from my POV it's important to push this feature into haskell
> standard

Haskell should be moving -toward- a capability-like model, not away from
it.
Bulat Ziganshin | 26 Aug 18:18

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

Hello Derek,

Tuesday, August 26, 2008, 8:14:21 PM, you wrote:

>> but from my POV it's important to push this feature into haskell
>> standard

> Haskell should be moving -toward- a capability-like model, not away from
> it.

what you mean by "capability-like model"?

--

-- 
Best regards,
 Bulat                            mailto:Bulat.Ziganshin <at> gmail.com
Derek Elkins | 26 Aug 18:28

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

On Tue, 2008-08-26 at 20:18 +0400, Bulat Ziganshin wrote:
> Hello Derek,
> 
> Tuesday, August 26, 2008, 8:14:21 PM, you wrote:
> 
> >> but from my POV it's important to push this feature into haskell
> >> standard
> 
> > Haskell should be moving -toward- a capability-like model, not away from
> > it.
> 
> what you mean by "capability-like model"?

http://erights.org/elib/capability/index.html
Adrian Hey | 26 Aug 19:34
Favicon

Re: [Haskell] Top Level <-

I have a feeling this is going to be a very long thread so I'm trying
to go to Haskell cafe again (without mucking it up again).

Derek Elkins wrote:
> Haskell should be moving -toward- a capability-like model, not away from
> it.

Could you show how to implement Data.Random or Data.Unique using such a
model, or any (preferably all) of the use cases identified can be
implemented? Like what about implementing the socket API starting with
nothing but primitives to peek/poke ethernet mac and dma controller
registers?

Why should Haskell should be moving -toward- a capability-like model and
why does top level <- declarations take us away from it?

Regards
--
Adrian Hey
Lennart Augustsson | 26 Aug 19:55
Favicon

Re: Re: [Haskell] Top Level <-

Making a network stack from peek and poke is easy in a well structured OS.
The boot loader (or whatever) hands you the capability (call it
something else if you want) to do raw hardware access, and you build
from there.  If you look at well structured OSs like NetBSD, this is
pretty much how they work.  No hardware drivers use global variables.

  -- Lennart

On Tue, Aug 26, 2008 at 6:34 PM, Adrian Hey <ahey <at> iee.org> wrote:
> I have a feeling this is going to be a very long thread so I'm trying
> to go to Haskell cafe again (without mucking it up again).
>
> Derek Elkins wrote:
>>
>> Haskell should be moving -toward- a capability-like model, not away from
>> it.
>
> Could you show how to implement Data.Random or Data.Unique using such a
> model, or any (preferably all) of the use cases identified can be
> implemented? Like what about implementing the socket API starting with
> nothing but primitives to peek/poke ethernet mac and dma controller
> registers?
>
> Why should Haskell should be moving -toward- a capability-like model and
> why does top level <- declarations take us away from it?
>
> Regards
> --
> Adrian Hey
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe <at> haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
Adrian Hey | 26 Aug 22:47
Favicon

Re: Re: [Haskell] Top Level <-

Lennart Augustsson wrote:
> Making a network stack from peek and poke is easy in a well structured OS.
> The boot loader (or whatever) hands you the capability (call it
> something else if you want) to do raw hardware access, and you build
> from there.  If you look at well structured OSs like NetBSD, this is
> pretty much how they work.  No hardware drivers use global variables.

So? We all know this is possible outside Haskell. But I don't want to
rely on mysterious black box OS's to "hand me the capability" any
more than I want to rely on mysterious extant but unimplementable libs
like Data.Unique. Most real world computing infrastructure uses no OS at
all. How could I use Haskell to implement such systems?

Also (to mis-quote Linus Torvalds) could you or anyone else who agrees
with you please SHOW ME THE CODE in *Haskell*! If scripture is all
that's on offer I'm just not going to take any of you seriously.

Frankly I'm tired of the patronising lectures that always acompany these
threads. It'd be good if someone who "knows" global variables are evil
could put their code where their mouth is for a change. Fixing up
the base libs to eliminate the dozen or so uses of the "unsafePerformIO
hack" might be a good place to start. I'll even let you change the API
of these libs if you must, provided you can give a sensible explanation
why the revised API is better, safer, more convenient or whatever.

Regards
--
Adrian Hey
Lennart Augustsson | 27 Aug 03:20
Favicon

Re: Re: [Haskell] Top Level <-

I told you where to look at code.  It's C code, mind you, but written
in a decent way.
No well written device driver ever accesses memory or IO ports
directly, doing so would seriously hamper portability.
Instead you use an abstraction layer to access to hardware, and the
driver gets passed a "bus" (whatever that might be) access token (akin
to a capability).

I know you're not going to be convinced, so I won't even try. :)

  -- Lennart

On Tue, Aug 26, 2008 at 9:47 PM, Adrian Hey <ahey <at> iee.org> wrote:
> Lennart Augustsson wrote:
>>
>> Making a network stack from peek and poke is easy in a well structured OS.
>> The boot loader (or whatever) hands you the capability (call it
>> something else if you want) to do raw hardware access, and you build
>> from there.  If you look at well structured OSs like NetBSD, this is
>> pretty much how they work.  No hardware drivers use global variables.
>
> So? We all know this is possible outside Haskell. But I don't want to
> rely on mysterious black box OS's to "hand me the capability" any
> more than I want to rely on mysterious extant but unimplementable libs
> like Data.Unique. Most real world computing infrastructure uses no OS at
> all. How could I use Haskell to implement such systems?
>
> Also (to mis-quote Linus Torvalds) could you or anyone else who agrees
> with you please SHOW ME THE CODE in *Haskell*! If scripture is all
> that's on offer I'm just not going to take any of you seriously.
>
> Frankly I'm tired of the patronising lectures that always acompany these
> threads. It'd be good if someone who "knows" global variables are evil
> could put their code where their mouth is for a change. Fixing up
> the base libs to eliminate the dozen or so uses of the "unsafePerformIO
> hack" might be a good place to start. I'll even let you change the API
> of these libs if you must, provided you can give a sensible explanation
> why the revised API is better, safer, more convenient or whatever.
>
> Regards
> --
> Adrian Hey
>
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe <at> haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
Adrian Hey | 27 Aug 10:07
Favicon

Re: Re: [Haskell] Top Level <-

Lennart Augustsson wrote:
> I told you where to look at code.  It's C code, mind you, but written
> in a decent way.
> No well written device driver ever accesses memory or IO ports
> directly, doing so would seriously hamper portability.

Well something must be accessing both. Dunno what you mean by "directly"
I take it you must mean that the driver does not make use of global
variables or "baked in" port addresses in it's source code.

> Instead you use an abstraction layer to access to hardware, and the
> driver gets passed a "bus" (whatever that might be) access token (akin
> to a capability).
> 
> I know you're not going to be convinced, so I won't even try. :)

I have actually spent the last 20 years or so writing both non-hosted
and hosted device drivers for a few OS's. I'm perfectly convinced about
the truth of what you say, but not at all convinced about the relevance.

It's a red herring IMO as you've introduced a very complex and
mysterious black box that itself cannot be implemented without making
use of "global variables". You can find them easily enough in the Linux
kernel source. I'm sure they'll be there in NetBSD too (never looked
though).

Regards
--
Adrian Hey
Lennart Augustsson | 27 Aug 10:32
Favicon

Re: Re: [Haskell] Top Level <-

I've also written quite a few hosted and non-hosted device drivers (in C).
None of them have any global variables.

On Wed, Aug 27, 2008 at 9:07 AM, Adrian Hey <ahey <at> iee.org> wrote:
> Lennart Augustsson wrote:
>>
>> I told you where to look at code.  It's C code, mind you, but written
>> in a decent way.
>> No well written device driver ever accesses memory or IO ports
>> directly, doing so would seriously hamper portability.
>
> Well something must be accessing both. Dunno what you mean by "directly"
> I take it you must mean that the driver does not make use of global
> variables or "baked in" port addresses in it's source code.
>
>> Instead you use an abstraction layer to access to hardware, and the
>> driver gets passed a "bus" (whatever that might be) access token (akin
>> to a capability).
>>
>> I know you're not going to be convinced, so I won't even try. :)
>
> I have actually spent the last 20 years or so writing both non-hosted
> and hosted device drivers for a few OS's. I'm perfectly convinced about
> the truth of what you say, but not at all convinced about the relevance.
>
> It's a red herring IMO as you've introduced a very complex and
> mysterious black box that itself cannot be implemented without making
> use of "global variables". You can find them easily enough in the Linux
> kernel source. I'm sure they'll be there in NetBSD too (never looked
> though).
>
> Regards
> --
> Adrian Hey
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe <at> haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
Adrian Hey | 27 Aug 10:54
Favicon

Re: Re: [Haskell] Top Level <-

Lennart Augustsson wrote:
> I've also written quite a few hosted and non-hosted device drivers (in C).
> None of them have any global variables.

The point is to be able to properly model, understand and if necessary
implement *entire systems* without using "global variables" (allegedly).

You can always define sub-system boundaries in such a way that you can
claim that this/that or the other sub-system, device driver or whatever
does not use "global variables" if you put the global variables
somewhere else and pass a reference to the sub-system concerned.
We could play that game with Data.Unique, for example.

Regards
--
Adrian Hey
Lennart Augustsson | 27 Aug 03:23
Favicon

Re: Re: [Haskell] Top Level <-

BTW, I'm not contradicting that the use of global variables can be
necessary when interfacing with legacy code, I just don't think it's
the right design when doing something new.

  -- Lennart

On Tue, Aug 26, 2008 at 9:47 PM, Adrian Hey <ahey <at> iee.org> wrote:
> Lennart Augustsson wrote:
>>
>> Making a network stack from peek and poke is easy in a well structured OS.
>> The boot loader (or whatever) hands you the capability (call it
>> something else if you want) to do raw hardware access, and you build
>> from there.  If you look at well structured OSs like NetBSD, this is
>> pretty much how they work.  No hardware drivers use global variables.
>
> So? We all know this is possible outside Haskell. But I don't want to
> rely on mysterious black box OS's to "hand me the capability" any
> more than I want to rely on mysterious extant but unimplementable libs
> like Data.Unique. Most real world computing infrastructure uses no OS at
> all. How could I use Haskell to implement such systems?
>
> Also (to mis-quote Linus Torvalds) could you or anyone else who agrees
> with you please SHOW ME THE CODE in *Haskell*! If scripture is all
> that's on offer I'm just not going to take any of you seriously.
>
> Frankly I'm tired of the patronising lectures that always acompany these
> threads. It'd be good if someone who "knows" global variables are evil
> could put their code where their mouth is for a change. Fixing up
> the base libs to eliminate the dozen or so uses of the "unsafePerformIO
> hack" might be a good place to start. I'll even let you change the API
> of these libs if you must, provided you can give a sensible explanation
> why the revised API is better, safer, more convenient or whatever.
>
> Regards
> --
> Adrian Hey
>
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe <at> haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
Adrian Hey | 27 Aug 09:42
Favicon

Re: Re: [Haskell] Top Level <-

Lennart Augustsson wrote:
> BTW, I'm not contradicting that the use of global variables can be
> necessary when interfacing with legacy code, I just don't think it's
> the right design when doing something new.

AFAICS the use of top level mutable state in the base libs has nothing
at all to do with interfacing with legacy code, it's a semantic
necessity and there's no legacy code involved.

If you want to dispute that then please show some real Haskell code that
does as good or better job without it (or point me too the relevant
legacy code that makes it necessary).

Regards
--
Adrian Hey
John Meacham | 27 Aug 11:35
Favicon

Re: Re: [Haskell] Top Level <-

On Wed, Aug 27, 2008 at 02:23:04AM +0100, Lennart Augustsson wrote:
> BTW, I'm not contradicting that the use of global variables can be
> necessary when interfacing with legacy code, I just don't think it's
> the right design when doing something new.

As with all design decisions, it is sometimes the right thing and
sometimes the wrong one. And sometimes the most expedient. (which,
occasionally, is a perfectly valid driving force behind a certain bit of
coding). However, I am fully convinced it is necessary. You don't even
have to look further than Haskell 98 to find a use in the Random module,
and Data.Unique _depends_ on the state being global for correctness.

now, _interfaces_ that depend on global state are a completely different
matter. To quote what I wrote in the jhc manual:

"Note, top level global variables can be indicative of design issues. In
general, they should only be used when necessary to interface with an
external library, opaque uses inside a library where the shared state
can not be externally observed, or inside your Main program as design
dictates."

However, note the weasel words. Those are in there on purpose, every
design calls for different solutions. To blanketly say certain
constructs are just wrong to the point of disallowing them in the
language, especially when they are common practice at the moment, just
doesn't seem right.

        John

--

-- 
John Meacham - ⑆repetae.net⑆john⑈
Adrian Hey | 27 Aug 12:53
Favicon

Re: Re: [Haskell] Top Level <-

John Meacham wrote:
> As with all design decisions, it is sometimes the right thing and
> sometimes the wrong one. And sometimes the most expedient. (which,
> occasionally, is a perfectly valid driving force behind a certain bit of
> coding). However, I am fully convinced it is necessary. You don't even
> have to look further than Haskell 98 to find a use in the Random module,
> and Data.Unique _depends_ on the state being global for correctness.

..and of course there's stdin, stdout. That takes some explaining. Even
with the proposed ACIO and top level <- bindings I still couldn't
implement a lib that exported a top level nonStdout handle. It'd have to
be a getNonStdout IO action.

Regarding the necessity of "global variables", despite what I've been
saying it is of course possible to implement entire systems
(programs/processes or whatever main corresponds to) without them if
you don't mind explicitly creating all those micro states immediately
on entry to main and passing the references around.

But this is a highly unmodular, inconvenient, unsafe (because you must
expose and allow potentially uncontrained use of newWhateverMicroState
constuctors) and a general maintainance nightmare. Definitely not the
way to go IMO.

So it would be more accurate to say that IMO it's impossible to
implement many sane and inherently safe IO lib APIs without using
"global variables". But people who prefer insane and inherently unsafe
APIs could live without them quite happily I guess :-)

Regards
--
Adrian Hey
Jonathan Cast | 27 Aug 18:12
Favicon

Re: Re: [Haskell] Top Level <-

On Wed, 2008-08-27 at 11:53 +0100, Adrian Hey wrote:
> John Meacham wrote:
> > As with all design decisions, it is sometimes the right thing and
> > sometimes the wrong one. And sometimes the most expedient. (which,
> > occasionally, is a perfectly valid driving force behind a certain bit of
> > coding). However, I am fully convinced it is necessary. You don't even
> > have to look further than Haskell 98 to find a use in the Random module,
> > and Data.Unique _depends_ on the state being global for correctness.
> 
> ..and of course there's stdin, stdout. That takes some explaining.

Not really.  If you don't have buffered IO, then you just say

stdin = 0
stdout = 1
stderr = 2

If you need buffered IO, you just change your IO monad* to look like:

newtype NewIO alpha = NewIO (ReaderT (Map Fd Buffer) OldIO alpha)

Of course, if you do this, you can't go mixing IO with unique values
with RNG with mutable state with everything else under the sun anymore.
You might actually have to declare exactly what effects you need when
you give your function's type, now.  Clearly, a horror we must avoid at
all costs.

jcc

* I wonder why that name was chosen?  The design doesn't seem to have
anything to do with IO, it's more of a `we have this in C so we want it
in Haskell too' monad.
Bulat Ziganshin | 27 Aug 22:53

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

Hello Jonathan,

Wednesday, August 27, 2008, 8:12:42 PM, you wrote:

> * I wonder why that name was chosen?  The design doesn't seem to have
> anything to do with IO, it's more of a `we have this in C so we want it
> in Haskell too' monad.

s/it/exchange with external world, i.e., essentially, I/O/


--

-- 
Best regards,
 Bulat                            mailto:Bulat.Ziganshin <at> gmail.com
Jonathan Cast | 27 Aug 22:57
Favicon

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

On Thu, 2008-08-28 at 00:53 +0400, Bulat Ziganshin wrote:
> Hello Jonathan,
> 
> Wednesday, August 27, 2008, 8:12:42 PM, you wrote:
> 
> > * I wonder why that name was chosen?  The design doesn't seem to have
> > anything to do with IO, it's more of a `we have this in C so we want it
> > in Haskell too' monad.
> 
> s/it/exchange with external world, i.e., essentially, I/O/

Bald assertion.  I don't buy it.  What do IORefs have to do with
exchange with the external world?

jcc
Bulat Ziganshin | 27 Aug 23:09

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

Hello Jonathan,

Thursday, August 28, 2008, 12:57:19 AM, you wrote:

>> s/it/exchange with external world, i.e., essentially, I/O/

> Bald assertion.  I don't buy it.  What do IORefs have to do with
> exchange with the external world?

IORefs got their names because they are implemented in IO monad :)

--

-- 
Best regards,
 Bulat                            mailto:Bulat.Ziganshin <at> gmail.com
Jonathan Cast | 27 Aug 23:11
Favicon

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

On Thu, 2008-08-28 at 01:09 +0400, Bulat Ziganshin wrote:
> Hello Jonathan,
> 
> Thursday, August 28, 2008, 12:57:19 AM, you wrote:
> 
> >> s/it/exchange with external world, i.e., essentially, I/O/
> 
> > Bald assertion.  I don't buy it.  What do IORefs have to do with
> > exchange with the external world?
> 
> IORefs got their names because they are implemented in IO monad :)

But why are they implemented in the IO monad?

jcc
Bulat Ziganshin | 27 Aug 23:23

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

Hello Jonathan,

Thursday, August 28, 2008, 1:11:35 AM, you wrote:
>> IORefs got their names because they are implemented in IO monad :)

> But why are they implemented in the IO monad?

because they need its features. but i/o may be implemented w/o IORefs.
so sequence was: searching for a was to make i/o in Haskell (you can
read about this in "History of Haskell"), finding monads as general
approach to implement side-effects, naming one of monads used to
interact with external world as IO, adding "variables" support to list
of operations of this monad

--

-- 
Best regards,
 Bulat                            mailto:Bulat.Ziganshin <at> gmail.com
Jonathan Cast | 27 Aug 23:50
Favicon

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

On Thu, 2008-08-28 at 01:23 +0400, Bulat Ziganshin wrote:
> Hello Jonathan,
> 
> Thursday, August 28, 2008, 1:11:35 AM, you wrote:
> >> IORefs got their names because they are implemented in IO monad :)
> 
> > But why are they implemented in the IO monad?
> 
> because they need its features. but i/o may be implemented w/o IORefs.
> so sequence was: searching for a was to make i/o in Haskell (you can
> read about this in "History of Haskell"), finding monads as general
> approach to implement side-effects,

Note that this was true even in Haskell 1.0: the Haskell report included
example code with definitions of (>>=) and return in the context of I/O,
but without the explicit recognition of the connection to monads.

> naming one of monads used to
> interact with external world as IO, adding "variables" support to list
> of operations of this monad

Do you really think I'm unaware of the history?  I know what happened,
what I don't understand is, looking at the matter from a language-design
perspective circa 2008, IORefs would go in the same monad as Handles.
What is the theoretical justification for this, independent of GHC's
current implementation of these and their requisite monad(s)?

jcc
Jonathan Cast | 27 Aug 23:55
Favicon

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

On Wed, 2008-08-27 at 14:50 -0700, Jonathan Cast wrote:
> On Thu, 2008-08-28 at 01:23 +0400, Bulat Ziganshin wrote:
> > Hello Jonathan,
> > 
> > Thursday, August 28, 2008, 1:11:35 AM, you wrote:
> > >> IORefs got their names because they are implemented in IO monad :)
> > 
> > > But why are they implemented in the IO monad?
> > 
> > because they need its features.

Oh, and by the way: what `features' of IO do IORefs use?  Other than the
fact that IO can implement anything in C, of course.

jcc
Lennart Augustsson | 28 Aug 00:00
Favicon

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

IMO, there's no justification for having IORefs etc in the IO monad.
They should be in a separate monad.  There could then be an operation
to lift that monad to the IO monad, if you so wish.
But wait, we already have that, it's the ST monad!  (So there is no
justification.)

  -- Lennart

On Wed, Aug 27, 2008 at 10:50 PM, Jonathan Cast
<jonathanccast <at> fastmail.fm> wrote:
> On Thu, 2008-08-28 at 01:23 +0400, Bulat Ziganshin wrote:
>> Hello Jonathan,
>>
>> Thursday, August 28, 2008, 1:11:35 AM, you wrote:
>> >> IORefs got their names because they are implemented in IO monad :)
>>
>> > But why are they implemented in the IO monad?
>>
>> because they need its features. but i/o may be implemented w/o IORefs.
>> so sequence was: searching for a was to make i/o in Haskell (you can
>> read about this in "History of Haskell"), finding monads as general
>> approach to implement side-effects,
>
> Note that this was true even in Haskell 1.0: the Haskell report included
> example code with definitions of (>>=) and return in the context of I/O,
> but without the explicit recognition of the connection to monads.
>
>> naming one of monads used to
>> interact with external world as IO, adding "variables" support to list
>> of operations of this monad
>
> Do you really think I'm unaware of the history?  I know what happened,
> what I don't understand is, looking at the matter from a language-design
> perspective circa 2008, IORefs would go in the same monad as Handles.
> What is the theoretical justification for this, independent of GHC's
> current implementation of these and their requisite monad(s)?
>
> jcc
>
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe <at> haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
Jonathan Cast | 28 Aug 00:26
Favicon

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

On Wed, 2008-08-27 at 23:00 +0100, Lennart Augustsson wrote:
> IMO, there's no justification for having IORefs etc in the IO monad.
> They should be in a separate monad.  There could then be an operation
> to lift that monad to the IO monad, if you so wish.
> But wait, we already have that, it's the ST monad!  (So there is no
> justification.)

Right.  We'd have ST (which has the advantage that, if you don't have
any free variables of STRef type, your code can be used in a pure
context), together with a monad homomorphism

  stToProgram :: ST RealWorld alpha -> Program alpha

We'd also have IO (stripped of IORef, Random, Unique, and other such
irrelevant ugliness), together with a monad homomorphism

  ioToProgram :: IO alpha -> Program alpha

Then, the top-level type rule would be

  Main.main :: Program ()

We'd flame people for using the Program monad outside of the Main module
or monad homomorphisms like ioToProgram or stToProgram.  Then, using the
functional programming language research of the last 20 years instead of
ignoring it for historical reasons, we'd get a free monad homomorphism

  ioAndStToProgram :: Coproduct IO (ST RealWorld) alpha -> Program alpha

which would let you use both in the same program.

It doesn't dispense with the need for top-level Program (yet), but it's
a step in the right direction.

jcc
Daniel Fischer | 27 Aug 23:20

Re: Re: [Haskell] Top Level <-

Am Mittwoch, 27. August 2008 22:57 schrieb Jonathan Cast:
> On Thu, 2008-08-28 at 00:53 +0400, Bulat Ziganshin wrote:
> > Hello Jonathan,
> >
> > Wednesday, August 27, 2008, 8:12:42 PM, you wrote:
> > > * I wonder why that name was chosen?  The design doesn't seem to have
> > > anything to do with IO, it's more of a `we have this in C so we want it
> > > in Haskell too' monad.
> >
> > s/it/exchange with external world, i.e., essentially, I/O/
>
> Bald assertion.  I don't buy it.  What do IORefs have to do with
> exchange with the external world?
>
> jcc
>

Well, you wrote
<snip>
> change your IO monad*
<snip>
> * I wonder why that name was chosen?  The design doesn't seem to have
> anything to do with IO, it's more of a `we have this in C so we want it
> in Haskell too' monad.

I believe, Bulat took it to include getLine, readFile, writeFile et al.
Jonathan Cast | 27 Aug 23:47
Favicon

Re: Re: [Haskell] Top Level <-

On Wed, 2008-08-27 at 23:20 +0200, Daniel Fischer wrote:
> Am Mittwoch, 27. August 2008 22:57 schrieb Jonathan Cast:
> > On Thu, 2008-08-28 at 00:53 +0400, Bulat Ziganshin wrote:
> > > Hello Jonathan,
> > >
> > > Wednesday, August 27, 2008, 8:12:42 PM, you wrote:
> > > > * I wonder why that name was chosen?  The design doesn't seem to have
> > > > anything to do with IO, it's more of a `we have this in C so we want it
> > > > in Haskell too' monad.
> > >
> > > s/it/exchange with external world, i.e., essentially, I/O/
> >
> > Bald assertion.  I don't buy it.  What do IORefs have to do with
> > exchange with the external world?
> >
> > jcc
> >
> 
> Well, you wrote
> <snip>
> > change your IO monad*
> <snip>
> > * I wonder why that name was chosen?  The design doesn't seem to have
> > anything to do with IO, it's more of a `we have this in C so we want it
> > in Haskell too' monad.
> 
> I believe, Bulat took it to include getLine, readFile, writeFile et al.

These things existed in Haskell 1.0, before IORefs ever did.

jcc
Ganesh Sittampalam | 27 Aug 23:29

Re: Re: [Haskell] Top Level <-

On Wed, 27 Aug 2008, Jonathan Cast wrote:

> * I wonder why that name was chosen?  The design doesn't seem to have
> anything to do with IO, it's more of a `we have this in C so we want it
> in Haskell too' monad.

The 'C' in ACIO says that it commutes with any operation in the IO
monad. Without that property you can't safely implement it in a
program where the top-level has type IO a.

http://www.haskell.org/pipermail/haskell-cafe/2004-November/007664.html

Ganesh
Favicon

Re: Re: [Haskell] Top Level <-

On 2008 Aug 27, at 12:12, Jonathan Cast wrote:
> * I wonder why that name was chosen?  The design doesn't seem to have
> anything to do with IO, it's more of a `we have this in C so we want  
> it
> in Haskell too' monad.

As I understand it, "IO" means "anything not encompassed by  
equationally-reasoned visible program state".  This includes  
randomness (the IO-based aspect of which requires process or OS  
state).  This also encompasses mutable state (e.g. IORefs), since  
mutability doesn't fit with equational reasoning.  So the name is  
perhaps poorly chosen, because it only encompasses the most common  
visible application.  (And IORefs particularly so, since they're only  
so named by analogy with STRefs.)

--

-- 
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery <at> kf8nh.com
system administrator [openafs,heimdal,too many hats] allbery <at> ece.cmu.edu
electrical and computer engineering, carnegie mellon university    KF8NH
Adrian Hey | 28 Aug 10:30
Favicon

Re: Re: [Haskell] Top Level <-

Jonathan Cast wrote:
> On Wed, 2008-08-27 at 11:53 +0100, Adrian Hey wrote:
>> John Meacham wrote:
>>> As with all design decisions, it is sometimes the right thing and
>>> sometimes the wrong one. And sometimes the most expedient. (which,
>>> occasionally, is a perfectly valid driving force behind a certain bit of
>>> coding). However, I am fully convinced it is necessary. You don't even
>>> have to look further than Haskell 98 to find a use in the Random module,
>>> and Data.Unique _depends_ on the state being global for correctness.
>> ..and of course there's stdin, stdout. That takes some explaining.
> 
> Not really.  If you don't have buffered IO, then you just say
> 
> stdin = 0
> stdout = 1
> stderr = 2

nonStdout = 42?

I'm afraid I have no idea what your point is :-(

I tried it anyway and doesn't seem to work, but that ain't so surprising
as Handles aren't Nums.

What needs explaining IMO is that we appear to have "global" Handles
exported at the top level from System.IO, but no way for users to write
their own modules that do the same for nonStdout, or even to implement
getNonStdout. I think that's pretty weird and inconsistent.

But perhaps you could show me how to do it with some real Haskell :-)

> If you need buffered IO, you just change your IO monad* to look like:
> 
> newtype NewIO alpha = NewIO (ReaderT (Map Fd Buffer) OldIO alpha)
> 
> Of course, if you do this, you can't go mixing IO with unique values
> with RNG with mutable state with everything else under the sun anymore.
> You might actually have to declare exactly what effects you need when
> you give your function's type, now.  Clearly, a horror we must avoid at
> all costs.

Indeed. If anyone thinks that's the way to go maybe Clean would be of
some interest. IMHO Cleans treatment of IO and concurrency is just about
the worst thing in an otherwise pretty decent language :-(

Regards
--
Adrian Hey
Derek Elkins | 27 Aug 19:17

Re: Re: [Haskell] Top Level <-

On Wed, 2008-08-27 at 02:35 -0700, John Meacham wrote:
[cut]
> 
> However, note the weasel words. Those are in there on purpose, every
> design calls for different solutions. To blanketly say certain
> constructs are just wrong to the point of disallowing them in the
> language, especially when they are common practice at the moment, just
> doesn't seem right.

How can a Haskell user say this?  And this is indeed exactly what
capability languages do.  In fact, this is what almost every language
does (for one thing in common practice or another.) 
John Meacham | 28 Aug 00:25
Favicon

Re: Re: [Haskell] Top Level <-

On Wed, Aug 27, 2008 at 12:17:46PM -0500, Derek Elkins wrote:
> On Wed, 2008-08-27 at 02:35 -0700, John Meacham wrote:
> > However, note the weasel words. Those are in there on purpose, every
> > design calls for different solutions. To blanketly say certain
> > constructs are just wrong to the point of disallowing them in the
> > language, especially when they are common practice at the moment, just
> > doesn't seem right.
> 
> How can a Haskell user say this?  And this is indeed exactly what
> capability languages do.  In fact, this is what almost every language
> does (for one thing in common practice or another.) 

But as a system designer I *need* things like peek/poke/ACIO etc. I am
the one implementing 'Random' or 'Data.Unique'. If I have to resort to C
code to do such things, that makes haskell unsuitable for a wide variety
of systems programming tasks (including implementing the haskell 98
libraries). I know it is certainly possible to do a lot of things in a
capability-based system. but you don