Re: [Haskell-cafe] global variables for foreign C functions
On Mon, Dec 01, 2008 at 05:30:33PM -0800, Judah Jacobson wrote: You can limit the size of that stub file using: foreign import ccall progname progname :: Ptr (Ptr CChar) which lets you access that global variable and write the getters/setters in Haskell rather than C. this solves my problems quite nicely indeed, but I still cannot figure how to write a setter function that actually works. That is to say, after: newCString new_name = poke progname this: putStrLn . show = peekCString = peek progname would return new_name, but the library, which is using progname to produce some debugging messages, doesn't seem to get it correctly: the original bits are gone, but instead of new_name I get some garbage. Thanks to everyone for the interesting and useful hints. Andrea ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables for foreign C functions
On Mon, Dec 1, 2008 at 4:39 PM, Andrea Rossato [EMAIL PROTECTED] wrote: Hello, I'm writing the bindings to a C library which uses, in some functions, global variables. To make it clearer, those functions need a global variable to be defined. A C program using my_function, one of the library functions, would look like: I don't think you can use the FFI to declare symbols for C. One not-so-pretty but effective way to do it is create a stub.c with the variables declared along with setting functions, then bind those functions like any other. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables for foreign C functions
On Mon, Dec 1, 2008 at 4:55 PM, Evan Laforge [EMAIL PROTECTED] wrote: On Mon, Dec 1, 2008 at 4:39 PM, Andrea Rossato [EMAIL PROTECTED] wrote: Hello, I'm writing the bindings to a C library which uses, in some functions, global variables. To make it clearer, those functions need a global variable to be defined. A C program using my_function, one of the library functions, would look like: I don't think you can use the FFI to declare symbols for C. One not-so-pretty but effective way to do it is create a stub.c with the variables declared along with setting functions, then bind those functions like any other. You can limit the size of that stub file using: foreign import ccall progname progname :: Ptr (Ptr CChar) which lets you access that global variable and write the getters/setters in Haskell rather than C. -Judah ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables for foreign C functions
On Mon, Dec 01, 2008 at 04:55:14PM -0800, Evan Laforge wrote: On Mon, Dec 1, 2008 at 4:39 PM, Andrea Rossato [EMAIL PROTECTED] wrote: Hello, I'm writing the bindings to a C library which uses, in some functions, global variables. To make it clearer, those functions need a global variable to be defined. A C program using my_function, one of the library functions, would look like: I don't think you can use the FFI to declare symbols for C. One not-so-pretty but effective way to do it is create a stub.c with the variables declared along with setting functions, then bind those functions like any other. Yes, it is unfortunate this is the case. my ForeignData proposal was meant to address this: http://hackage.haskell.org/trac/haskell-prime/wiki/ForeignData I am not entirely sure about the proposal as described, but I think something like it should be done. John -- John Meacham - ⑆repetae.net⑆john⑈ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables for foreign C functions
I would find a ForeignData extension incredibly helpful. This will be crucial if Haskell ever wants to target out of the ordinary systems. /jve On Mon, Dec 1, 2008 at 8:38 PM, John Meacham [EMAIL PROTECTED] wrote: On Mon, Dec 01, 2008 at 04:55:14PM -0800, Evan Laforge wrote: On Mon, Dec 1, 2008 at 4:39 PM, Andrea Rossato [EMAIL PROTECTED] wrote: Hello, I'm writing the bindings to a C library which uses, in some functions, global variables. To make it clearer, those functions need a global variable to be defined. A C program using my_function, one of the library functions, would look like: I don't think you can use the FFI to declare symbols for C. One not-so-pretty but effective way to do it is create a stub.c with the variables declared along with setting functions, then bind those functions like any other. Yes, it is unfortunate this is the case. my ForeignData proposal was meant to address this: http://hackage.haskell.org/trac/haskell-prime/wiki/ForeignData I am not entirely sure about the proposal as described, but I think something like it should be done. John -- John Meacham - ⑆repetae.net⑆john⑈ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Taral wrote: On 5/23/07, Adrian Hey [EMAIL PROTECTED] wrote: I think I still prefer.. var :: IORef Int var - newIORef 3 So do I. For one very good reason: this syntax could be defined as a constructor syntax and guaranteed to run before main. Or even at compile time (which is why I think it's reasonable to regard operations like newIORef etc.. as not really being IO operations at all). But anyway, the constraints of the ACIO monad allow creation to occur at any time before the first attempt to read or write the IORef. The other syntaxes proposed don't strike me as sufficiently rigorous. Me neither. It's always been a great source of puzzlement to me why this very simple and IMO conservative proposal should be so controversial. Unless someone can point out some severe semantic difficulty or suggest something better it seems like a no-brainer to me. Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On 5/24/07, Adrian Hey [EMAIL PROTECTED] wrote: Taral wrote: The other syntaxes proposed don't strike me as sufficiently rigorous. Me neither. It's always been a great source of puzzlement to me why this very simple and IMO conservative proposal should be so controversial. Unless someone can point out some severe semantic difficulty or suggest something better it seems like a no-brainer to me. I think it lacks implementation. I don't have time, or I'd look into hacking this into GHC. -- Taral [EMAIL PROTECTED] Please let me know if there's any further trouble I can give you. -- Unknown ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Adrian Hey wrote: Taral wrote: On 5/23/07, Adrian Hey [EMAIL PROTECTED] wrote: I think I still prefer.. var :: IORef Int var - newIORef 3 So do I. For one very good reason: this syntax could be defined as a constructor syntax and guaranteed to run before main. Or even at compile time (which is why I think it's reasonable to regard operations like newIORef etc.. as not really being IO operations at all). But anyway, the constraints of the ACIO monad allow creation to occur at any time before the first attempt to read or write the IORef. The other syntaxes proposed don't strike me as sufficiently rigorous. Me neither. It's always been a great source of puzzlement to me why this very simple and IMO conservative proposal should be so controversial. Unless someone can point out some severe semantic difficulty or suggest something better it seems like a no-brainer to me. This is going to be highly subjective, but to me it still doesn't feel like it falls under the bar for implementation cost given its usefulness. The new syntax requires additions all the way through the front end of the compiler: parser, abstract syntax, renamer, type checker, desugarer, for something that is rarely used. It's a first-class language construct (a new top-level binding form, no less), and it has to pay its way. Also you want to add the ACIO monad as a built-in to the language. Not that my gut feeling should in any way be considered the final word on the subject, but I thought I should say something about why we're not running to implement this right now. To me it seems like we should let it simmer some more. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On 24/05/07, Adrian Hey [EMAIL PROTECTED] wrote: Or even at compile time (which is why I think it's reasonable to regard operations like newIORef etc.. as not really being IO operations at all). You can allocate heap space at compile time? (Well, I guess you could, but that wouldn't still be usable at run time...) I imagine newIORef as mallocing() some room, then returning a pointer to that memory. That doesn't seem like something that could be done at compile time. -- -David House, [EMAIL PROTECTED] ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
David House wrote: On 24/05/07, Adrian Hey [EMAIL PROTECTED] wrote: Or even at compile time (which is why I think it's reasonable to regard operations like newIORef etc.. as not really being IO operations at all). You can allocate heap space at compile time? (Well, I guess you could, but that wouldn't still be usable at run time...) I imagine newIORef as mallocing() some room, then returning a pointer to that memory. That doesn't seem like something that could be done at compile time. There seems to be quite a few implicit (and incorrect) assumptions in your argument, which is fallacious IMO. The logic of your argument would imply that *no* top level expression can be evaluated at compile time. This might be the case with ghc, though I doubt it (and even if it was this would just be a ghc problem). BTW, the Haskell standard says nothing about any kind of heap, let alone a C style malloc. Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On 2007-05-24, David House wrote: On 24/05/07, Adrian Hey [EMAIL PROTECTED] wrote: Or even at compile time (which is why I think it's reasonable to regard operations like newIORef etc.. as not really being IO operations at all). You can allocate heap space at compile time? (Well, I guess you could, but that wouldn't still be usable at run time...) I imagine newIORef as mallocing() some room, then returning a pointer to that memory. That doesn't seem like something that could be done at compile time. You can allocate bss or data space at compile time for the executable you are compiling. (Well, if you read compile as compile and link. It's a bit fuzzy.) -- Aaron Denney -- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Aaron Denney wrote: On 2007-05-24, David House wrote: On 24/05/07, Adrian Hey [EMAIL PROTECTED] wrote: Or even at compile time (which is why I think it's reasonable to regard operations like newIORef etc.. as not really being IO operations at all). You can allocate heap space at compile time? (Well, I guess you could, but that wouldn't still be usable at run time...) I imagine newIORef as mallocing() some room, then returning a pointer to that memory. That doesn't seem like something that could be done at compile time. You can allocate bss or data space at compile time for the executable you are compiling. (Well, if you read compile as compile and link. It's a bit fuzzy.) Well we don't need to get too bogged down with the details of how any particular compiler/linker/rts might work. The point being that with any.. myIORef - newIORef initialExpression whether or not it's at the top level, the only information needed to create the IORef is the initialExpression, and if it's at the top level then this is available at compile time (it doesn't even have to be evaluated at compile time in order to create the IORef). But it doesn't require any information from, nor should it have any effect on, the outside world that an executing program is interacting with. It is conceivable that for some newIORef implementations this would not be true, but in that case it's difficult to see how such implementations could safely put their newIORef in the ACIO monad anyway. Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Isaac Dupree wrote: var :: IORef Int var = {-# EVALUATE_THIS_TEXT_ONLY_ONCE #-} (unsafePerformIO (newIORef 3)) I think I still prefer.. var :: IORef Int var - newIORef 3 or, more likely.. var :: IORef Int var - ACIO.newIORef 3 The - syntax should make the intended semantics clear and unambiguous, so it becomes the problem of individual implementors (not standards writers) to make sure that whatever optimisations or transformations that may be appropriate for their implementation preserve those semantics. (IOW there's no need to worry about what a pragma really means in operational terms, AFAICS). The ACIO monad also restricts what programmers may use on the rhs of the -. But if you want a good name for the pragma how about this.. var :: IORef Int var = {-# - #-} (unsafePerformIO (newIORef 3)) :-) Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On 5/23/07, Adrian Hey [EMAIL PROTECTED] wrote: I think I still prefer.. var :: IORef Int var - newIORef 3 So do I. For one very good reason: this syntax could be defined as a constructor syntax and guaranteed to run before main. The other syntaxes proposed don't strike me as sufficiently rigorous. -- Taral [EMAIL PROTECTED] Please let me know if there's any further trouble I can give you. -- Unknown ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Isaac Dupree wrote: Maybe some sort of ISOLATE, DON'T_OPTIMIZE (but CAF), or USED_AS_GLOBAL_VARIABLE pragma instead of just the insufficient NOINLINE would be a good first step... if successful it would remove the occasional need for -fno-cse for a whole module in GHC, at least. ISOLATE, DON'T_OPTIMIZE are actually bad names for the whole effect, which requires persistent CAF semantics. An implementation that doesn't make top-level definitions be CAFs, or even one that is willing to garbage-collect them when memory is tight such that they need recalculation later, would need a special case for global variables to make them work. i.e. I'm not sure if there exists a reasonable pragma while the code still uses unsafePerformIO. Hmm How about so, {-# NOINLINE var #-} var :: IORef Int var = unsafePerformIO (newIORef 3) - -- var :: IORef Int var = {-# EVALUATE_THIS_TEXT_ONLY_ONCE #-} (unsafePerformIO (newIORef 3)) to capture the desired semantics: text-based uniqueness, no duplication, no sharing of the IORefs (sharing the pure contents is fine), and no need to actually evaluate it any times at all. {-# EVALUATE_THIS_TEXT_ONLY_ONCE #-} is syntactically like a (special) function. Clearly it is an impossible demand for polymorphic things, so the compiler could complain (at least a warning) if the (var :: IORef Int) line was left off, for example. I guess it would also complain about non-type(class) argument dependencies too such as (f x = (unsafePerformIO (newIORef (x::Int))) )... Food for thought :-) Isaac -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGU02YHgcxvIWYTTURAoCaAKCkDH7Pd7JbNt0TmNig9j7ujiUV9ACZAevI QOjdmMbrPfVrKBafZshCh7c= =9/5v -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] global variables
| I see no need two answer this again I believe I have already made my | views perfectly clear already and provided ample evidence to justify | them. Surely I don't need to do it again? Is there a Wiki page about this somewhere? Often email gets into a loop because not everyone reads everything on Haskell Cafe. (There's just too much of it.) When that happens, a good thing do to is to summarise the various positions on a Wiki page, so the debate can progress by refining text rather than by repeating it. There is the additional advantage that someone coming along later can still make sense of the debate. Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On 21-mei-2007, at 9:31, Simon Peyton-Jones wrote: | I see no need two answer this again I believe I have already made my | views perfectly clear already and provided ample evidence to justify | them. Surely I don't need to do it again? Is there a Wiki page about this somewhere? Often email gets into a loop because not everyone reads everything on Haskell Cafe. (There's just too much of it.) When that happens, a good thing do to is to summarise the various positions on a Wiki page, so the debate can progress by refining text rather than by repeating it. There is the additional advantage that someone coming along later can still make sense of the debate. As I am sure Adrian would tell you were he awake: http://www.haskell.org/haskellwiki/Top_level_mutable_state With regards, Arthur van Leeuwen -- /\/ | [EMAIL PROTECTED] | Work like you don't need the money /__\ / | A friend is someone with whom | Love like you have never been hurt /\/__ | you can dare to be yourself | Dance like there's nobody watching ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Jules Bean wrote: I've pretty much convinced it's wrong. There should be one and only one main from which all subsequent IO activity derives. But creating internal state in the form of mutable data structures is not an IO activity. It just so happens that at the moment the only way to do this is newIORef :: a - IO(IORef a), but this need not be so (readIORef and writeIORef are IO activities, but newIORef isn't). I find this point rather slippery. 'newIORef' is a unique-name-provider, but 'unique over what'? When a module is imported twice, should it not create new unique names? No, it's just binding a name to a value, same as any other binding. The difference is unlike normal top level bindings, that name is not equal to any other expression. It just is, if you get what I mean (I'm sure you do). That's why the proposed syntax borrows the - from do expressions. If it's necessary that there is only one libWhateverState to preserve safety properties (because the state must be kept in sync with what's really being done to the world, of which there is also only one) then what's the point of making it a parameter (the lib is not truly parameterisable by that state). A slightly irrational point of concern in my mind is that by encouraging this practice, we encourage lazy library design. Yes, this is slightly irrational :-) A large proportion of libraries in fact *can* be written as reentrant in this sense, and truly are parameterisable by their state. I can't help being sceptical about this. AFAICS it doesn't matter how many explicit state handles you tack on to the left of the - IO Whatever, the fact that the whole lot ends in - IO Whatever means there's almost certainly some state left unaccounted for and unparameterised (calls the OS are missing an OS state handle for example). Also, I don't really understand what you mean by reentrant in this context. Are you talking about thread safety? (I guess not) Are you implying that APIs of IO libs that mutate Haskell global state are some how different from other IO APIs which mutate other global state (such as OS state or world state)? Are they deficient in some way? If so, how can you tell the difference? Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Adrian Hey wrote: Jules Bean wrote: I've pretty much convinced it's wrong. There should be one and only one main from which all subsequent IO activity derives. But creating internal state in the form of mutable data structures is not an IO activity. It just so happens that at the moment the only way to do this is newIORef :: a - IO(IORef a), but this need not be so (readIORef and writeIORef are IO activities, but newIORef isn't). I find this point rather slippery. 'newIORef' is a unique-name-provider, but 'unique over what'? When a module is imported twice, should it not create new unique names? No, it's just binding a name to a value, same as any other binding. The difference is unlike normal top level bindings, that name is not equal to any other expression. It just is, if you get what I mean (I'm sure you do). That's why the proposed syntax borrows the - from do expressions. That's not my point. newIORef creates unique names (references). The whole job of newIORef is to create unique names; unique names which refer to little tiny bits of state parcelled up somewhere in that mysterious IO monad. It is the scope of this uniqueness I'm talking about: do libraries need these unique names to be unique over each importer, over each thread, over each subprocess: consider a haskell application server or a haskell OS... what is the correct domain of uniqueness? A large proportion of libraries in fact *can* be written as reentrant in this sense, and truly are parameterisable by their state. I can't help being sceptical about this. AFAICS it doesn't matter how many explicit state handles you tack on to the left of the - IO Whatever, the fact that the whole lot ends in - IO Whatever means there's almost certainly some state left unaccounted for and unparameterised (calls the OS are missing an OS state handle for example). Also, I don't really understand what you mean by reentrant in this context. Are you talking about thread safety? (I guess not) Are you implying that APIs of IO libs that mutate Haskell global state are some how different from other IO APIs which mutate other global state (such as OS state or world state)? Are they deficient in some way? If so, how can you tell the difference? 'reentrant' is not the right word, although it's a related notion. I was talking about libraries which can safely be initialised more than once, for multiple clients, and they keep around 'separate' state for each client/each time they are initialised. This kind of design is often a precondition for being thread-safe; and it's often plain good design, unless some external 'real world' uniqueness makes it impossible. Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
[cc'ing HPrime] Isaac Dupree wrote: The unsafePerformIO hack being used is not very satisfactory given how many optimizations make it difficult to use safely in practice. This hack is also used many places. I would be happier if that situation were not true, and I suspect there's something like a consensus on _that_. (maybe not as strong as _needs_ a solution in the short-to-mid term future) Considering the value that the Haskell community normally places on sound semantics, reliance on such an appalling hack seems pretty bad to me. If a solution doesn't find it's way into H' then how many more years is it going to be with us? It's just embarrassing :-) Also, I don't know if the OP was a noob, but telling people (especially noobs) that if they can't figure out how to solve a problem without using a global variable then that must be down to inexperience and general cluelessness on their part just seems wrong to me. It simply isn't true. (Anyone who disagrees with this should feel free to submit the patches needed to fix up the base package :-) Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Adrian Hey wrote: [cc'ing HPrime] Isaac Dupree wrote: The unsafePerformIO hack being used is not very satisfactory given how many optimizations make it difficult to use safely in practice. This hack is also used many places. I would be happier if that situation were not true, and I suspect there's something like a consensus on _that_. (maybe not as strong as _needs_ a solution in the short-to-mid term future) Considering the value that the Haskell community normally places on sound semantics, reliance on such an appalling hack seems pretty bad to me. If a solution doesn't find it's way into H' then how many more years is it going to be with us? It's just embarrassing :-) Yes, also it places value on REALLY EXTREMELY (excessively?) SOUND semantics, and on the modularity of the language even more than the modularity of its uses (or something like that :-) Maybe some sort of ISOLATE, DON'T_OPTIMIZE (but CAF), or USED_AS_GLOBAL_VARIABLE pragma instead of just the insufficient NOINLINE would be a good first step... if successful it would remove the occasional need for -fno-cse for a whole module in GHC, at least. Isaac -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGUF4yHgcxvIWYTTURAvqWAJ46eFRt5LK1lUwqr2BmHVSrHljxzwCfYGJB x5ivAFEw5vYKbxTPIg+PrIU= =0xVK -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Isaac Dupree wrote: Maybe some sort of ISOLATE, DON'T_OPTIMIZE (but CAF), or USED_AS_GLOBAL_VARIABLE pragma instead of just the insufficient NOINLINE would be a good first step... if successful it would remove the occasional need for -fno-cse for a whole module in GHC, at least. I have a hard time trying to understand why anyone would prefer this to the simple and clear - syntax that's been proposed. As for the ACIO monad itself, this is utterly trivial and requires no language change. It's just a library. Maybe the first pragma you propose might have other uses to control optimisations, so I'm not totally anti this. But generally I dislike pragmas (I always find myself wondering what's wrong with the language design that makes the pragma necessary). So pragmas that influence optimisation are something I can live with. But using pragmas to influence *semantics* really is an evil practice IMO and is something that should be discouraged, not made an unavoidable necessity. But yes, if this problem isn't going to be properly addressed then at the very least the -fno-cse flag or something similar needs standardising (NOINLINE already is I think). Or we port all existing unsafePerfomIO hacked code to use Johm Meachams variant of the hack (uses types to ensure the compiler doesn't see common sub-expressions). Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Adrian Hey wrote: Also, I don't know if the OP was a noob, but telling people (especially noobs) that if they can't figure out how to solve a problem without using a global variable then that must be down to inexperience and general cluelessness on their part just seems wrong to me. It simply isn't true. Then what is right and what is true? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Jules Bean wrote: That's not my point. newIORef creates unique names (references). The whole job of newIORef is to create unique names; unique names which refer to little tiny bits of state parcelled up somewhere in that mysterious IO monad. It is the scope of this uniqueness I'm talking about: do libraries need these unique names to be unique over each importer, over each thread, over each subprocess: consider a haskell application server or a haskell OS... what is the correct domain of uniqueness? The scoping rules are exactly the same as for any other top level identifier, whether or not exported or imported. There's no reason why an importing module should know or care that one or more of the identifiers it's importing is the result of a - binding. Should every module that imports the prelude get a different stdout? (they currently don't of course) 'reentrant' is not the right word, although it's a related notion. I was talking about libraries which can safely be initialised more than once, for multiple clients, and they keep around 'separate' state for each client/each time they are initialised. This kind of design is often a precondition for being thread-safe; and it's often plain good design, unless some external 'real world' uniqueness makes it impossible. I don't see a problem here. The fact that an IO lib presents some controlled interface one or more to real world resources (I.E. resources where you can't simply conjour up a new ones by using a newResource constructor) should not stop it being able to service multiple clients or sessions. The socket API and indeed the OS itself seem to be obvious examples of this (or even something really simple like Data.Unique). Or take a look at the hypothetical embedded device driver API I put on the wiki. This makes a clear distinction between DeviceHandles and DeviceSessionHandles (which will wrap the correspnding DeviceHandle). Users cannot create new DeviceHandles but are free to create as many DeviceSessionHandles with a particular device as they like. Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Albert Y. C. Lai wrote: Adrian Hey wrote: Also, I don't know if the OP was a noob, but telling people (especially noobs) that if they can't figure out how to solve a problem without using a global variable then that must be down to inexperience and general cluelessness on their part just seems wrong to me. It simply isn't true. Then what is right and what is true? I see no need two answer this again I believe I have already made my views perfectly clear already and provided ample evidence to justify them. Surely I don't need to do it again? If you disagree with any of them then feel free to explain why. Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] global variables
| and (at worst) are evil. These people are quite simply wrong and | should be ignored :-) | | Adrian Hey is not only wrong, but actually evil. He should be ignored. :-) | | I am right, I might well be evil, and if past experience is anything to | go by I already know that I will be ignored. We've been talking about | this problem for years, but nothing is ever done about it I know that Jules preceded his remarks by saying that they were lighthearted, but I'd like to urge moderation in language. One of the best things about the Haskell community is that politeness is pretty much universal. Email is too fragile a medium to sustain the wry smile that can accompany an in-person conversation. Also Adrian, you may feel ignored, but I don't think that's really so. For example, I was looking back at your ACIO mail a couple of months ago, when I was thinking about concurrency. Not immediately achieving a critical mass behind a language change is not the same as being ignored. One of the good things about Haskell is that we put up with woefully inadequate situations (such as the total lack of sensible I/O in early lazy languages) because we can't yet find a solution that feels satisfying. To say that nothing is ever done about it implies that there are clear things that could be done, but I don't think that is so (yet). And sometimes people don't reply because they are just busy, or because they don't have anything useful to say. In short, don't be discouraged. Keep identifying problems, suggesting solutions, maintaining Wiki pages that summarise both, and so on. There are lots of bright people on this mailing list, and sooner or later an aha moment will happen. Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On Thu, 17 May 2007, Jules Bean wrote: Eric wrote: H|i, Does anyone know of a simple and straightforward way to use global variables in Haskell? (Perhaps annoyingly) the answer to this question, like so many other questions on this list, is a question. What are you trying to do?. I've put your answer to the FAQ category on Haskell-Wiki: http://haskell.org/haskellwiki/Global_variables ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
[I agree with your points, but...] Adrian Hey wrote: I've pretty much convinced it's wrong. There should be one and only one main from which all subsequent IO activity derives. But creating internal state in the form of mutable data structures is not an IO activity. It just so happens that at the moment the only way to do this is newIORef :: a - IO(IORef a), but this need not be so (readIORef and writeIORef are IO activities, but newIORef isn't). I find this point rather slippery. 'newIORef' is a unique-name-provider, but 'unique over what'? When a module is imported twice, should it not create new unique names? Indeed they do, unfortunately. In fact it was this very problem that lead me to conclude the top level mutable state is not only not evil, but is a necessity. Having to call explicit initialisation code is a big problem in complex systems. Exactly who is responsible for initialising what? and in what order? Maybe I'm being old-fashioned here, but isn't that a *fundamental* problem, that can't be automatically solved? Isn't it just a fact that in a complex system you, the programmer, have to make some decisions about who is responsible for acquiring resources? If it's necessary that there is only one libWhateverState to preserve safety properties (because the state must be kept in sync with what's really being done to the world, of which there is also only one) then what's the point of making it a parameter (the lib is not truly parameterisable by that state). A slightly irrational point of concern in my mind is that by encouraging this practice, we encourage lazy library design. A large proportion of libraries in fact *can* be written as reentrant in this sense, and truly are parameterisable by their state. Only a few are not: those which actually manage connections to some real entity which is in fact unique. Of course that doesn't mean the problem doesn't exist. Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Jules Bean wrote: main = do sockstate - initSocks graphstate - initGraphics ... disposeGraphics graphstate disposeSocks sockstate exit Voila. Mutable state which persists for our entire program. Arguably it's a pain passing around the state explicitly. Alternatively, you can argue that passing this stuff around explicitly makes code much easier to reason about. And we know a dozen tricks to hide this stuff (reader monads, state monads, withSocketsDo-style bracket constructs). So I don't think this is really the issue, is it? Have you ever wondered why our IO API's don't look like this? I think there are many problems with this approach. What are the consequences of this philosophy for issues such safety, platform independence, maintainance of stable APIs? As I understood it, the issue was more about whether or not *library* modules should be allowed to some 'set up' initialisation code to run at the beginning of 'main' to start up their own global state. I was never convinced this was a nice idea (I don't like the thought than an 'import' alone can add hidden IO actions to main). I agree, which is why I'm not keen on the top level mdo proposal. But addressing this issue is the point of the ACIO monad proposal. Mind you, I'm not convinced it's wrong, either. I think it's a hard one. I've pretty much convinced it's wrong. There should be one and only one main from which all subsequent IO activity derives. But creating internal state in the form of mutable data structures is not an IO activity. It just so happens that at the moment the only way to do this is newIORef :: a - IO(IORef a), but this need not be so (readIORef and writeIORef are IO activities, but newIORef isn't). I wouldn't dispute the assertion that at the level of complete programs or processes, implementations that don't use global variables are possible. But this does not hold at the level of individual IO library API's. If we want to keep our software *modular* (I take we do), then we need top level mutable state. That's assuming you feel having an explicit 'init' command and a 'withLibXYZDo' construct breaks modularity. It doesn't feel like a terrible modularity break to me. (Plenty of C libraries I've used require explicit init calls). Indeed they do, unfortunately. In fact it was this very problem that lead me to conclude the top level mutable state is not only not evil, but is a necessity. Having to call explicit initialisation code is a big problem in complex systems. Exactly who is responsible for initialising what? and in what order? You could make it the users responsibility to do it right at the begining of main. But this places a heavy burden on the user to fully understand the dependencies of their hardware and the software that controls it. Or you could make it the users responsibility to initialise whatever APIs they actually make use of, in no particular order. Those APIs then initialise whatever sub-systems they actually use as part of their own initialisation. But what happens if the same sub-system is used (and initialised) by two different higher level IO libs? (The second will initialisation will destroy any state that the first may have set up.) Of course it's perfectly straight forward to avoid accidental re-initialisation, but only by making use of..you know what. Is it the use of global variables? Or is it the use of the unsafePerformIO hack to create them? The latter is definitely a problem. Yes. The former, I'm not sure. My gut feeling is that it is, too. If it's necessary that there is only one libWhateverState to preserve safety properties (because the state must be kept in sync with what's really being done to the world, of which there is also only one) then what's the point of making it a parameter (the lib is not truly parameterisable by that state). Furthermore, if it is going to take this state handle as an explicit argument then you need to provide some way for users to get this state handle. This could be by.. 1 - Making it an argument of main. 2 - Exposing a newLibWhateverState constructor 3 - Exposing a getLibWhateverState getter. Problems.. 1 Requires the type of main to depend on what IO libs are used. Also the Boot code that invokes main must get this state handle from somewhere. 2 Potentially permits 2 or more libWhateverStates to be created (in which case all bets are off re. the safety proprties I was talking about). 3 Can't be implemented without making use of..you know what. Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Simon Peyton-Jones wrote: For example, I was looking back at your ACIO mail a couple of months ago, when I was thinking about concurrency. Actually, this is Ian Starks proposal.. http://www.haskell.org/pipermail/haskell-cafe/2004-November/007664.html ..but is one with which I agree. I just wrote some stuff on the wiki about this actually solved some currently insoluble problems. Not immediately achieving a critical mass behind a language change is not the same as being ignored. Unfortunately the situation seems worse than this. AFAICT we haven't even got a consensus that that there is a real problem here that needs any kind of solution :-) Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Adrian Hey wrote: Furthermore, if it is going to take this state handle as an explicit argument then you need to provide some way for users to get this state handle. This could be by.. 1 - Making it an argument of main. 2 - Exposing a newLibWhateverState constructor 3 - Exposing a getLibWhateverState getter. Problems.. 1 Requires the type of main to depend on what IO libs are used. Also the Boot code that invokes main must get this state handle from somewhere. 2 Potentially permits 2 or more libWhateverStates to be created (in which case all bets are off re. the safety proprties I was talking about). 3 Can't be implemented without making use of..you know what. Making it an argument of main (1) is somewhat the same as doing (3) - consider getArgs. What bothers me is the IO-state in the Haskell standard (arguments, random state...) which is a set not extensible without the hack. (It bothers me that there _are_ so many things in that set, somewhat ad-hoc-ly it seems :) Unfortunately the situation seems worse than this. AFAICT we haven't even got a consensus that that there is a real problem here that needs any kind of solution :-) The unsafePerformIO hack being used is not very satisfactory given how many optimizations make it difficult to use safely in practice. This hack is also used many places. I would be happier if that situation were not true, and I suspect there's something like a consensus on _that_. (maybe not as strong as _needs_ a solution in the short-to-mid term future) Isaac -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGTg2+HgcxvIWYTTURAvWfAKC36q24IKTX5YQOVi+A4gNYLzBMMACePwkL dwnAlZh++e2EqiFKvJEmn1M= =NBHG -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On Thu, May 17, 2007 at 07:25:03PM +0100, Adrian Hey wrote: The above hack is not actually Haskell. It's a hack, and it depends on the particular implementation characteristics of GHC. It is not unreasonable to imagine that a future GHC might contain different compilation techniques (I hesitate to use the word 'optimisations' because that sounds like something easy to turn off) which invalidate the technique in other ways or make it dangerous. Well of course, that's why something needs to be done about this. Just being in a state of complete denial regarding the reality of this problem won't make it go away. Indeed, I made a proposal a while ago to allow top level IO actions, foo - newIORef foo which are quite straigtforward, and would not even be inconsistant in the view of the type system, as - bindings are always monomorphic anyway. Others pointed out that if we allow arbitrary IO actions, it could cause undesirable things like causing importing a mobule to change program behavior, or expose implementatino details, like when these are executed, right away or lazily. The solution was to have a special restricted version of IO containing only those actions that are safe. like newMVar etc.. where safe means more or less commutative and omittable. this doesn't require any special support, just a newtype ACIO a = ACIO (IO a) deriving(Monad,Functor) and then have a module only export the trusted things in the ACIO monad. John -- John Meacham - ⑆repetae.net⑆john⑈ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On Thu, May 17, 2007 at 11:00:18PM +0100, Jules Bean wrote: I'm not sure that's quite to the point. Clearly we can set up state at the top of our main action: main = do sockstate - initSocks graphstate - initGraphics ... disposeGraphics graphstate disposeSocks sockstate exit Voila. Mutable state which persists for our entire program. Arguably it's a pain passing around the state explicitly. Alternatively, you can argue that passing this stuff around explicitly makes code much easier to reason about. And we know a dozen tricks to hide this stuff (reader monads, state monads, withSocketsDo-style bracket constructs). So I don't think this is really the issue, is it? As I understood it, the issue was more about whether or not *library* modules should be allowed to some 'set up' initialisation code to run at the beginning of 'main' to start up their own global state. I was never convinced this was a nice idea (I don't like the thought than an 'import' alone can add hidden IO actions to main). Mind you, I'm not convinced it's wrong, either. I think it's a hard one. indeed. the whole issue is libraries. global state need not be visible to users, but is certainly useful when hidden inside librarys to provide efficient purely functional veneers for internal algorithms. I think restricting the actions to ones that don't have externally visible effects is the way to go here for a couple reasons. * I would very much hate for 'import' to have effects in and of itself. * it would disallow (or expose) the obvious 'lazy' approach to top-level IO, where you don't actually perform the IO until the first time the value is needed, then memoize it. so, some sort of restricted ACIO monad is in order. Also, there is the somewhat related 'ForeignData' proposal of mine, the syntax is pretty much off the top of my head, but I think something like this needs to go into the haskell FFI, http://hackage.haskell.org/trac/haskell-prime/wiki/ForeignData especially since it will sever the last need for C, allowing fully native haskellp programs with the full power of C code. (plus, lots of optimizatuons are available to the compiler when it sees the definitions like this and it is really easy to implement) John -- John Meacham - ⑆repetae.net⑆john⑈ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
eeoam: H|i, Does anyone know of a simple and straightforward way to use global variables in Haskell? E. The usual way is to run the code that needs a global variable in a State monad. The next answer is: you don't really need global variables, since you don't have mutable variables anyway :-) -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On 17/05/07, Eric [EMAIL PROTECTED] wrote: H|i, Does anyone know of a simple and straightforward way to use global variables in Haskell? You can pass around an environment with the State or Reader monads (read/write and read-only respectively). If you want to do IO with the data you'll probably need the transformer equivalents: StateT or ReaderT. I think there are some hackish ways of making IO variables but I don't know how that's done. I'd imagine it's frowned on from a stylistic point of view, too... D. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
You can also use mutable variables (MVars) found in Control.Concurrent.MVar http://haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent-MVar.html They might work depending on your implementation. The reading and writing of MVars returns IO actions. On 5/17/07, Dougal Stanton [EMAIL PROTECTED] wrote: On 17/05/07, Eric [EMAIL PROTECTED] wrote: H|i, Does anyone know of a simple and straightforward way to use global variables in Haskell? You can pass around an environment with the State or Reader monads (read/write and read-only respectively). If you want to do IO with the data you'll probably need the transformer equivalents: StateT or ReaderT. I think there are some hackish ways of making IO variables but I don't know how that's done. I'd imagine it's frowned on from a stylistic point of view, too... D. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- Tom Harper Computer Science Major '07 Syracuse University +1 949 235 0185 Public Key: http://aftereternity.co.uk/rth.asc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On Thu, 17 May 2007 14:41:33 +0100 Eric [EMAIL PROTECTED] wrote: H|i, Does anyone know of a simple and straightforward way to use global variables in Haskell? E. Another alternative, for write-once variables, is implicit parameters. -- Robin ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On Thu, May 17, 2007 at 02:41:33PM +0100, Eric wrote: Does anyone know of a simple and straightforward way to use global variables in Haskell? Just declare them at the top level, as a function but without arguments: === x = 2 main = print x === Stefan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Eric wrote: H|i, Does anyone know of a simple and straightforward way to use global variables in Haskell? (Perhaps annoyingly) the answer to this question, like so many other questions on this list, is a question. What are you trying to do?. The reason for this is that haskell's abstractions are different from those of the mainstream imperative languages, and the mapping isn't 1-1. So for a particular 'C' feature, there may be 3 or 4 haskell features which achieve similar effects, and the correct choice depends on the detailed context. So, in particular, all those tasks which you use global variables for in C, can be achieved in haskell, but which solution depends what you are trying to do: 1. If you have some globals which are constant, then just define them at the top level. No problem. pi = 3.14; progname = MyCoolApp. 2. If you have a global environment, which various functions read from (and you might, for example, initialise from a configuration file) then you should thread that as a parameter to your functions (after having, very likely, set it up in your 'main' action). If the explicit parameter passing annoys you, then you can 'hide' it with a monad. 3. If you have a need to store some global state which various of your functions modify, then you have a design issue. This style of design is frowned upon in C as well! The correct solution in C is to pass a 'bundle' of appropriate parameters (you might call it an environment) to those functions which need it. In C++, perl or python you'd very likely make this bundle an object. In haskell this bundle will be a data value in some custom type; and using Monads you can 'hide the details' of passing it around, if you wish. Hope that helps a bit, Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Eric wrote: H|i, Does anyone know of a simple and straightforward way to use global variables in Haskell? I assume what you're looking for is to be able to have IORefs,MVars Chans etc at the top level. The standard (for want of a better word) way to do this is known commonly known as the unsafePerformIO hack. myTopLevelFlag :: IORef Bool {-# NOINLINE myTopLevelFlag #-} myTopLevelFlag = unsafePerformIO (newIORef False) With ghc you should also compile which make use of the unsafePerformIO hack using the -fno-cse flag (to inhibit common sub-expression elemination). Use something like this at the top of the module.. {-# OPTIONS_GHC -fno-cse #-} BTW, this is the commonly the subject of flame wars on the Haskell mailing lists because there appear to be many who passionately believe and assert that so called global variables are (at best) unnecessary and (at worst) are evil. These people are quite simply wrong and should be ignored :-) They are necessary because they are the only way to ensure important safety properties of many IO APIs. I ported the old wiki page about this to the new wiki.. http://www.haskell.org/haskellwiki/Top_level_mutable_state If you want to see more examples of the use of the unsafePerformIO hack you need only look at the source code of the current base package (you'll find a dozen or so uses of this hack to create top level mutable state). Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Please take this message in the fashion that is intended. My criticism is light hearted, as I believe yours is. Adrian Hey wrote: [hack snipped] BTW, this is the commonly the subject of flame wars on the Haskell mailing lists because there appear to be many who passionately believe and assert that so called global variables are (at best) unnecessary and (at worst) are evil. These people are quite simply wrong and should be ignored :-) Adrian Hey is not only wrong, but actually evil. He should be ignored. :-) The above hack is not actually Haskell. It's a hack, and it depends on the particular implementation characteristics of GHC. It is not unreasonable to imagine that a future GHC might contain different compilation techniques (I hesitate to use the word 'optimisations' because that sounds like something easy to turn off) which invalidate the technique in other ways or make it dangerous. They are necessary because they are the only way to ensure important safety properties of many IO APIs. That's a bold claim. It's very hard to prove that things don't exist. (That is, that other ways to ensure these safety properties don't exist). In snipped text you comment that the problems are often in low-level FFI library code: this makes me wonder if the real culprit doesn't lie at the FFI-haskell boundary. Perhaps there are good ways to specify this kind of invariant there. If you want to see more examples of the use of the unsafePerformIO hack you need only look at the source code of the current base package (you'll find a dozen or so uses of this hack to create top level mutable state). All of these are, in a sense, failings. Because unsafePerformIO is not haskell, and we'd like base to be a haskell library. Not a GHC library. I'd be willing to take a sportsman's bet that the original poster does not actually need to use this hack; I doubt his application falls into the categories you have outlined. I would discourage people from using this hack unless it is, in fact, the only feasible approach. Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On 17/05/07, Jules Bean [EMAIL PROTECTED] wrote: I'd be willing to take a sportsman's bet that the original poster does not actually need to use this hack; I doubt his application falls into the categories you have outlined. I would discourage people from using this hack unless it is, in fact, the only feasible approach. I find it amusing that questions like these elicit such a wide variety of responses. The original poster probably thought they were asking a fairly straightforward question and then... woosh :-) Everyone responds to the question at the level that suits their own proficiency in the subject, I suppose. D. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Jules Bean wrote: BTW, this is the commonly the subject of flame wars on the Haskell mailing lists because there appear to be many who passionately believe and assert that so called global variables are (at best) unnecessary and (at worst) are evil. These people are quite simply wrong and should be ignored :-) Adrian Hey is not only wrong, but actually evil. He should be ignored. :-) I am right, I might well be evil, and if past experience is anything to go by I already know that I will be ignored. We've been talking about this problem for years, but nothing is ever done about it (a solution to this problem isn't even on the agenda for Haskell' AFIAK). The above hack is not actually Haskell. It's a hack, and it depends on the particular implementation characteristics of GHC. It is not unreasonable to imagine that a future GHC might contain different compilation techniques (I hesitate to use the word 'optimisations' because that sounds like something easy to turn off) which invalidate the technique in other ways or make it dangerous. Well of course, that's why something needs to be done about this. Just being in a state of complete denial regarding the reality of this problem won't make it go away. They are necessary because they are the only way to ensure important safety properties of many IO APIs. That's a bold claim. It's very hard to prove that things don't exist. (That is, that other ways to ensure these safety properties don't exist). In snipped text you comment that the problems are often in low-level FFI library code: this makes me wonder if the real culprit doesn't lie at the FFI-haskell boundary. Perhaps there are good ways to specify this kind of invariant there. No. Even if we stripped away all other code apart from the Haskell rts itself (OS, device drivers etc) and performed your IO entirely in Haskell (just using peek and poke on bare hardware), you'd still need top level mutable state to implement common IO API's (e.g. The socket API, does anybody really believe this is entirely stateless?). I wouldn't dispute the assertion that at the level of complete programs or processes, implementations that don't use global variables are possible. But this does not hold at the level of individual IO library API's. If we want to keep our software *modular* (I take we do), then we need top level mutable state. If you want to see more examples of the use of the unsafePerformIO hack you need only look at the source code of the current base package (you'll find a dozen or so uses of this hack to create top level mutable state). All of these are, in a sense, failings. Because unsafePerformIO is not haskell, and we'd like base to be a haskell library. Not a GHC library. But what's the problem? Is it the use of global variables? Or is it the use of the unsafePerformIO hack to create them? Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Adrian Hey wrote: They are necessary because they are the only way to ensure important safety properties of many IO APIs. That's a bold claim. It's very hard to prove that things don't exist. (That is, that other ways to ensure these safety properties don't exist). In snipped text you comment that the problems are often in low-level FFI library code: this makes me wonder if the real culprit doesn't lie at the FFI-haskell boundary. Perhaps there are good ways to specify this kind of invariant there. No. Even if we stripped away all other code apart from the Haskell rts itself (OS, device drivers etc) and performed your IO entirely in Haskell (just using peek and poke on bare hardware), you'd still need top level mutable state to implement common IO API's (e.g. The socket API, does anybody really believe this is entirely stateless?). I wouldn't dispute the assertion that at the level of complete programs or processes, implementations that don't use global variables are possible. But this does not hold at the level of individual IO library API's. If we want to keep our software *modular* (I take we do), then we need top level mutable state. If you want to see more examples of the use of the unsafePerformIO hack you need only look at the source code of the current base package (you'll find a dozen or so uses of this hack to create top level mutable state). All of these are, in a sense, failings. Because unsafePerformIO is not haskell, and we'd like base to be a haskell library. Not a GHC library. But what's the problem? Is it the use of global variables? Or is it the use of the unsafePerformIO hack to create them? It's only slightly the unsafePerformIO hack, IMHO - if that were all, a mechanism not requiring it would have been implemented long ago. Now I launch into a long discussion: The difficult question is how global?. GHCi already has problems with this (varying persistence of those global variables, and they never last between separate invocations of ghci). Obviously global variables to truly be global should be shared with one persistent state across the whole wide world forever :P - but then we get identity problems, e.g. fancy-package:GlobalVariable.Fancy.nuclearMissilesLaunched :: IORef/MVar MannerOfNuclearMissileLaunch where one day or on one hacker's computer there is type MannerOfNuclearMissileLaunch = Int --number launched already and another, data MannerOfNuclearMissileLaunch = NoMissilesLaunched | WorldDestroyed | Unknown The usual meaning relies on the size of a program invocation. This is a link to main:Main.main . As you observe, this is like inserting a wrapper over everywhere the IO monad is used. Clearly this adds modularity by not requiring main's code to be modified, and also destroys modularity by forcing main's semantics to be modified. A Haskell program is notionally executed by running Main.main. Consider: global foo (initial value: False) main1 = setGlobal foo True main2 = getGlobal foo = print Compile with -main-is main1 to the binary 'main1' and with -main-is main2 to the binary 'main2'. Now consider two possible overall definitions of main: main = main1 main2 or main = executeBinary main1 executeBinary main2 Basically, all existing operating systems require executing a binary to be more than just running its IO monad; they set up a global (process-specific) environment for the process, which is why the two hypothetical example defintions of main give different results. Note that operating systems also serve the root of filesystems / in unix, and variables global to the root filesystem's sharedness can be simulated in this way. Operating systems could serve process-specific spaces this way, as long as it is possible for them to define something like getProcessID :: IO ProcessID. Note that Haskell has ThreadID which is usefully Eq-comparable in GHC, whereas Hugs chooses not to distinguish the identity of threads. It is a similar design tradeoff. Hardware: readHardware, writeHardware are IO specific to the hardware. Kernels generally rely on storing information in RAM about the state of the hardware, and they presume to have global variables whose scope is the present run of the computer. This is straightforward for monolithic kernel designs. Although, if you want persistent settings it is more difficult, the system explicitly saving ALSA state to disk or whatever. Operating systems: I don't know sockets in particular, but indeed operating systems are expected to provide some IO operations that don't do exactly the same thing depending on which computer in the world the program is running on. Kernel/OS design variation is certainly one area to look into for further consideration of these issues. There are non-monolithic kernels (GNU Hurd...), systems that can run on multiple hardware-computers as a cluster... There is usually expected to be one name resolver (e.g.
Re: [Haskell-cafe] global variables
Adrian Hey wrote: We've been talking about this problem for years, but nothing is ever done about it (a solution to this problem isn't even on the agenda for Haskell' AFIAK). The problem needs talking about, it's important. My objection was the implication that top-level mutable state was the right answer to the OP's question, which my strong hunch is it isn't. I don't deny the existence of a problem here. No. Even if we stripped away all other code apart from the Haskell rts itself (OS, device drivers etc) and performed your IO entirely in Haskell (just using peek and poke on bare hardware), you'd still need top level mutable state to implement common IO API's (e.g. The socket API, does anybody really believe this is entirely stateless?). I'm not sure that's quite to the point. Clearly we can set up state at the top of our main action: main = do sockstate - initSocks graphstate - initGraphics ... disposeGraphics graphstate disposeSocks sockstate exit Voila. Mutable state which persists for our entire program. Arguably it's a pain passing around the state explicitly. Alternatively, you can argue that passing this stuff around explicitly makes code much easier to reason about. And we know a dozen tricks to hide this stuff (reader monads, state monads, withSocketsDo-style bracket constructs). So I don't think this is really the issue, is it? As I understood it, the issue was more about whether or not *library* modules should be allowed to some 'set up' initialisation code to run at the beginning of 'main' to start up their own global state. I was never convinced this was a nice idea (I don't like the thought than an 'import' alone can add hidden IO actions to main). Mind you, I'm not convinced it's wrong, either. I think it's a hard one. I wouldn't dispute the assertion that at the level of complete programs or processes, implementations that don't use global variables are possible. But this does not hold at the level of individual IO library API's. If we want to keep our software *modular* (I take we do), then we need top level mutable state. That's assuming you feel having an explicit 'init' command and a 'withLibXYZDo' construct breaks modularity. It doesn't feel like a terrible modularity break to me. (Plenty of C libraries I've used require explicit init calls). Is it the use of global variables? Or is it the use of the unsafePerformIO hack to create them? The latter is definitely a problem. The former, I'm not sure. My gut feeling is that it is, too. Jules ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
Albert Y. C. Lai wrote: There is no reality about global variables. Global variables are syntactic sugar for local variables. That is the reality we need to think through. This syntactic sugar streamlines many practical programs and is indeed valuable. I agree that the use of the term global variable is both inaccurate an highly emotive, which is why I don't like it. But even the term I use (top level mutable state) is not entirely accurate. The mutable state is not at the top level, the mutable state is already part of the world before main starts running. What is top level are references to that state (IORefs, MVars etc). As these are perfectly ordinary (I.E. *immutable*) Haskell values there doesn't seem to be any obvious reason why they should not exist at the top level. All that's missing is a semantically sound mechanism to achieve this (such as the ACIO monad proposal). Regards -- Adrian Hey ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] global variables
On 5/17/07, Adrian Hey [EMAIL PROTECTED] wrote: Jules Bean wrote: BTW, this is the commonly the subject of flame wars on the Haskell mailing lists because there appear to be many who passionately believe and assert that so called global variables are (at best) unnecessary and (at worst) are evil. These people are quite simply wrong and should be ignored :-) Adrian Hey is not only wrong, but actually evil. He should be ignored. :-) I am right, I might well be evil, and if past experience is anything to go by I already know that I will be ignored. We've been talking about this problem for years, but nothing is ever done about it (a solution to this problem isn't even on the agenda for Haskell' AFIAK). The above hack is not actually Haskell. It's a hack, and it depends on the particular implementation characteristics of GHC. It is not unreasonable to imagine that a future GHC might contain different compilation techniques (I hesitate to use the word 'optimisations' because that sounds like something easy to turn off) which invalidate the technique in other ways or make it dangerous. Well of course, that's why something needs to be done about this. Just being in a state of complete denial regarding the reality of this problem won't make it go away. They are necessary because they are the only way to ensure important safety properties of many IO APIs. That's a bold claim. It's very hard to prove that things don't exist. (That is, that other ways to ensure these safety properties don't exist). In snipped text you comment that the problems are often in low-level FFI library code: this makes me wonder if the real culprit doesn't lie at the FFI-haskell boundary. Perhaps there are good ways to specify this kind of invariant there. No. Even if we stripped away all other code apart from the Haskell rts itself (OS, device drivers etc) and performed your IO entirely in Haskell (just using peek and poke on bare hardware), you'd still need top level mutable state to implement common IO API's (e.g. The socket API, does anybody really believe this is entirely stateless?). At this point in the discussion I always think Haskell could probably take a lesson from the evolution of object oriented programming. As I was taught, people starting to see modules as an important abstraction (yay, Haskell has those). Then people started to also realize that instead of just modules it would be useful to have abstract data types which could be instantiated many times and sort of encapsulate the things (state) you might store in a module (yay, Haskell has ADTs). Eventually, people put the two together, data types that also encapsulated functionality. Around this time, it was sort of like having modules that could be instantiated many times instead of once per program and objects were essentially born. Well, it seems to me that Haskell modules are actually very similar to singletons. Perhaps all these problems with modules having top level mutable state could be solved if Haskell modules were parameterizable at instantiation? I'm not saying we should turn the Haskell module system into an OO system, just that maybe it would be wise to borrow some ideas from that paradigm. Jason ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Global Variables and IO initializers
Benjamin Franksen [EMAIL PROTECTED] writes: We could reduce the pain of applying the C wrapper solution a bit by adding some support in the FFI. I imagine a feature to allow writing small C wrappers around imported foreign routines directly inside the Haskell module. Such a facility is already available - the FFI pre-processor `GreenCard' allows you to write in-line C code in your Haskell module. Regards, Malcolm ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Global Variables and IO initializers
(stdin,stdout,stderr) seem to naturally have this scope (assuming you don't use freopen). There needs to be only one Handle created for each of these because otherwise the buffering won't work properly. Global - initializers seem like the right thing here. I think I would rather have them passed to 'main' as arguments... Afterall, what if somone calls hClose on one? The fact that a function may fail (on a closed handle) due to an action taken in another function (closing the handle) is not nice... Passing the handles explicitly might make things more obvious. A more functional way would be to reference count the handle, and only really close it then the last reference is closed or goes out of scope. I guess you wouldn't want a huge number of arguments to main, so a record would let you have all the 'environment' in one variable. Are there any others? The fact that the concept of 'one program' is artificial (created by the loading process used by the OS), it would suggest that OS variables associated with the process (IE process-ID, or anything stored in the OS's process-table may have a natural lifetime of one process - although these days most of these things tend to be associated with threads instead (thread-id etc...) and many threads can start and end in the life of a program. I cannot think of any library that could not be written in a multiple reference way - if it wasn't dependant on some legacy code. Even a library to manage a single physical piece of hardware (say a special encryption chip) would be better written allowing more than one chip to be supported - even if current hardware does not allow this - some future system might, and you don't want to have to change the software-architecture because of this... Far better to allow multiple threads to independantly open multiple devices - and limit the number of devices to 1 for now. In this case the OS would need to manage the device-counter. A nice way to do this would be to use the FFI to get the operating system to manage this. You could use an OS semaphore or a unix-socket. If you use the PID as part of the socket name, then only the first call to open-socket would succeed. This suggests that a nice library to make this sort of thing easy would be a 'namedChannel' library, where read and write ends of a channel could be opened independantly and the address would be an arbitrary string. Keean. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Global Variables and IO initializers
I think the broad issue is that there are many different levels of the system at which something can be global: a module, a thread, a process, a user, a computer, a network segment, the internet, the universe, etc.. If your model of a concept is more global than the concept itself, you lose flexibility. If your model is less global than the concept, you get cache-coherency problems. The global variables we're talking about here are global to a single invocation of a Haskell program [*] [**]. The only concepts which are appropriately modeled by such globals are those whose natural scope is a single invocation of a Haskell program. Are there any? Adrian Hey's example of a badly-written C library is one. But I agree with Robert Dockins that such cases are better solved in C than in Haskell. (stdin,stdout,stderr) seem to naturally have this scope (assuming you don't use freopen). There needs to be only one Handle created for each of these because otherwise the buffering won't work properly. Global - initializers seem like the right thing here. Are there any others? -- Ben [*] Adrian Hey has argued that global variables aren't really global. I think he's talking about hiding them through module scoping. What I mean by global is different: something is global at a particular level of the system if there's only one instance of it at that level. [**] Wouldn't it make sense to support thread-local global state also, if we're going to support process-local global state? ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Global Variables and =?utf-8?q?IO=09initializers?=
On Tuesday 09 November 2004 03:18, Ben Rudiak-Gould wrote: Adrian Hey's example of a badly-written C library is one. But I agree with Robert Dockins that such cases are better solved in C than in Haskell. Yes. Your code won't depend on compiler (dependent) flags to disable optimizations, which for my taste is just a little bit too obscure and is anyway non-portable. What follows are very raw ideas. Please bear with me if you think it is nonsense. We could reduce the pain of applying the C wrapper solution a bit by adding some support in the FFI. I imagine a feature to allow writing small C wrappers around imported foreign routines directly inside the Haskell module. Such code would need to be quoted properly (e.g. encoded as Haskell string, similar to the foreign entity names now). Eiffel has such a feature for its own variant of FFI and it has proven quite useful in practice. I know of at least one other case where such a feature might be helpful, namely for APIs where C structures get passed by value. At the moment one has to either lie to the FFI (declare the routine as if teh structure fields were passed separately, after checking that this is ok with respect to argument order and alignment) or else write a C wrapper routine (which is somewhat safer and more portable). The advantage of doing it through FFI support is that we avoid encouraging bad programming style by making global mutable variables an all too easily accessible and apparently safe feature. I have some ideas how to handle stdxyz without using global state but they are not though out and it is too late now anyway. Ben -- Top level things with identity are evil.-- Lennart Augustsson ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe