Re: unsafePerformIO safety.
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Simon Marlow wrote: > You're right that sometimes you really want it to be inlined - this is > why there's a function called inlinePerformIO in Data.ByteString.Base, > for example. You'd better really know what you're doing before using > that one, though :-) yep, it should be generally available as unsafeInlineUnsafePerformIO (-: It's especially unsafe because... all of the IO might not be executed, due to lazy evaluation + optimization? Some of the IO might be run twice without other parts of it being so? Isaac -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.3 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFF7p9jHgcxvIWYTTURAqAKAKCu8dJ4rpyMcMH7ebPv0HfIUyGSgACgy0Jq naeTCZk/2xZraOrSJtyObm8= =oKKG -END PGP SIGNATURE- ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO safety.
Lennart Augustsson wrote: I wouldn't like if unsafePerformIO could never be inlined, sometimes you want it inlined for performance. And not all uses are hacky, it's just that when I use it, then burden is on me to convince myself that it is safe. unsafePerformIO is currently not inlined - there's a NOINLINE pragma on its definition in GHC.IOBase, and some comments in there to explain why. You're right that sometimes you really want it to be inlined - this is why there's a function called inlinePerformIO in Data.ByteString.Base, for example. You'd better really know what you're doing before using that one, though :-) Cheers, Simon ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO safety.
I wouldn't like if unsafePerformIO could never be inlined, sometimes you want it inlined for performance. And not all uses are hacky, it's just that when I use it, then burden is on me to convince myself that it is safe. On Mar 6, 2007, at 23:56 , Neil Mitchell wrote: Hi On 3/6/07, Lennart Augustsson <[EMAIL PROTECTED]> wrote: Yeah, you really need {-# NOINLINE var #-} to make it reasonable safe. Couldn't GHC bake in knowledge about unsafePerformIO, and never inline it? It is a slightly hacky solution, but since unsafePerformIO is pretty much only used in hacks, I think its almost fitting. Thanks Neil ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO safety.
Neil Mitchell wrote: > On 3/6/07, Lennart Augustsson <[EMAIL PROTECTED]> wrote: >> Yeah, you really need {-# NOINLINE var #-} to make it reasonable safe. > > Couldn't GHC bake in knowledge about unsafePerformIO, and never inline > it? It is a slightly hacky solution, but since unsafePerformIO is > pretty much only used in hacks, I think its almost fitting. It seems to be used a bit more than just as a hack. Many things that interface with the real world, but try to present lazy interfaces have to use it. Maintaining a shared state that doesn't have to be passed around to everything that uses it isn't really a hack. As an example, I would like to have something that performs logging, and is used by many clients. Without the unsafePerformIO, everything has to somehow find and pass around the state of this logging system, whereas with it, it can just allocate one when first needed. Non-strict semantics are kind of a new thing for me. I'm still trying to get a good grasp of what can be lazy, what should live in the IO Monad, and what should have a carefully crafted "bridge" between the two. Things like hGetContents have somewhat set a trend here. Dave ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO safety.
Hi On 3/6/07, Lennart Augustsson <[EMAIL PROTECTED]> wrote: Yeah, you really need {-# NOINLINE var #-} to make it reasonable safe. Couldn't GHC bake in knowledge about unsafePerformIO, and never inline it? It is a slightly hacky solution, but since unsafePerformIO is pretty much only used in hacks, I think its almost fitting. Thanks Neil ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO safety.
Yeah, you really need {-# NOINLINE var #-} to make it reasonable safe. On Mar 6, 2007, at 23:18 , David Brown wrote: Seth Kurtzberg wrote: On Tue, 06 Mar 2007 12:03:05 -0800 David Brown <[EMAIL PROTECTED]> wrote: I've noticed quite a few pages referencing constructs such as: var :: MVar ([Foo]) var = unsafePerformIO (newMVar ([])) and the likes. Is there a danger of different uses of 'var' getting new MVars instead of all sharing one. Having a reliable way to create a piece of global state would be very convenient. This operation is unsafe by definition. I use it extensively, without problems. The "unsafe" in the name reminds you that there are situations for which the function is inappropriate, but all of my deployed commercial programs have functionality of this sort. Understand the risk, but don't hesitate to use it. Do you do anything to keep 'var' from getting inlined? I can envision a case where the code would be inlined, and then each use would get a separate MVar. Thanks, Dave ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO safety.
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 David Brown wrote: > I've noticed quite a few pages referencing constructs such as: > > var :: MVar ([Foo]) > var = unsafePerformIO (newMVar ([])) > > and the likes. Is there a danger of different uses of 'var' getting > new MVars instead of all sharing one. If I remember correctly, you "should" put {-# NOINLINE var #-} on a line just before that. > > Having a reliable way to create a piece of global state would be very > convenient. This is well known and extensively discussed - unfortunately it is a complicated (or at least controversial) issue Isaac -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.3 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFF7fiFHgcxvIWYTTURAoMXAJ9SCryCX+daNLKrMIhWlMh/aJmVXwCghosx 6/lBweYnNslHLal57RAtX0Y= =2oIN -END PGP SIGNATURE- ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO safety.
Seth Kurtzberg wrote: > On Tue, 06 Mar 2007 12:03:05 -0800 > David Brown <[EMAIL PROTECTED]> wrote: > >> I've noticed quite a few pages referencing constructs such as: >> >> var :: MVar ([Foo]) >> var = unsafePerformIO (newMVar ([])) >> >> and the likes. Is there a danger of different uses of 'var' getting >> new MVars instead of all sharing one. >> >> Having a reliable way to create a piece of global state would be very >> convenient. > > This operation is unsafe by definition. I use it extensively, > without problems. The "unsafe" in the name reminds you that there > are situations for which the function is inappropriate, but all of > my deployed commercial programs have functionality of this sort. > Understand the risk, but don't hesitate to use it. Do you do anything to keep 'var' from getting inlined? I can envision a case where the code would be inlined, and then each use would get a separate MVar. Thanks, Dave ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO safety.
On Tue, 06 Mar 2007 12:03:05 -0800 David Brown <[EMAIL PROTECTED]> wrote: > I've noticed quite a few pages referencing constructs such as: > > var :: MVar ([Foo]) > var = unsafePerformIO (newMVar ([])) > > and the likes. Is there a danger of different uses of 'var' getting > new MVars instead of all sharing one. > > Having a reliable way to create a piece of global state would be very > convenient. This operation is unsafe by definition. I use it extensively, without problems. The "unsafe" in the name reminds you that there are situations for which the function is inappropriate, but all of my deployed commercial programs have functionality of this sort. Understand the risk, but don't hesitate to use it. Seth Kurtzberg > > Dave > > ___ > Glasgow-haskell-users mailing list > Glasgow-haskell-users@haskell.org > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO and NOINLINE Pragma
Am Dienstag, 13. September 2005 16:13 schrieb David Sabel: > Hi, > > > Hi! > > > > I want to analyse the laziness of a data structure. To check how many > > nodes are constructed I use a global counter. > > > > counter :: IORef Int > > counter = unsafePerformIO (newIORef 0) > > > > This counter is increased every time the constructor is called by > > redefining the constructor OBDD as follows. > > > > oBDD low var high = > > seq (unsafePerformIO (modifyIORef counter (+1))) (OBDD low var high) > > > > This works fine. > > When I compile with optimisations the counter is always set to one no > > matter how many nodes are constructed. I thought this would be caused by > > inlining. Therefore I have added two NOINLINE pragmata. > > > > {-# NOINLINE counter #-} > > {-# NOINLINE oBDD #-} > > > > Although the counter doesn't work. Is there another optimisation that can > > cause harm? Is there something wrong with the pragmata? > > Two comments: > 1. There are other optimisations than inlining that can break sharing, e.g. >common subexpression elimination, full-laziness-transformation. > > 2. I tested the following: > > {-# NOLINE counter #-} > {-# INLINE oBDD #-} > > then the counter "seems" to work correct. In my opinion > oBDD is an abstraction and can always be inlined. Sadly this solution doesn't work in my environment. The counter is always set to 2 while it should be something around 15.000. I think it's not worth going into detail of the transformations for me thus I will check the number of nodes without optimisations and the performance with optimisations. Thanks anyway. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO and NOINLINE Pragma
Hi, > Hi! > > I want to analyse the laziness of a data structure. To check how many nodes > are constructed I use a global counter. > > counter :: IORef Int > counter = unsafePerformIO (newIORef 0) > > This counter is increased every time the constructor is called by redefining > the constructor OBDD as follows. > > oBDD low var high = > seq (unsafePerformIO (modifyIORef counter (+1))) (OBDD low var high) > > This works fine. > When I compile with optimisations the counter is always set to one no matter > how many nodes are constructed. I thought this would be caused by inlining. > Therefore I have added two NOINLINE pragmata. > > {-# NOINLINE counter #-} > {-# NOINLINE oBDD #-} > > Although the counter doesn't work. Is there another optimisation that can > cause harm? Is there something wrong with the pragmata? Two comments: 1. There are other optimisations than inlining that can break sharing, e.g. common subexpression elimination, full-laziness-transformation. 2. I tested the following: {-# NOLINE counter #-} {-# INLINE oBDD #-} then the counter "seems" to work correct. In my opinion oBDD is an abstraction and can always be inlined. Cheer, David ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO
Sven Panne wrote: Huh? I'm not sure what you mean exactly, but with the help of unsafePerformIO and a pragma for clever compilers you can simulate something like a global variable in Haskell. Here an excerpt from the GLUT menu handling module: {-# NOINLINE theMenuTable #-} theMenuTable :: IORef MenuTable theMenuTable = unsafePerformIO (newIORef emptyMenuTable) ... Definitely not something to be proud of, but quite handy from time to time. :-) Alternatives are passing the IORef to every function which needs it (but this would clutter up the GLUT API in the above case) or using the FFI for holding global data on the C side. GHC uses a similar hack internally, too, BTW. This is not just handy from time to time, but very frequently. I've just discovered it occurs about 100 times in 100K LOC that I am responsible for, so often that I have stopped feeling guilty about it. I don't really know what else I could do. One solution would be to use implicit parameters to pass a global state variable around, but this would require me to change the type of huge numbers of functions, since implicit parameters are still explicit in types. I don't remember having any actual bugs caused by unsafePerformIO. Well, only one, before I knew about putting NOINLINE in. ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO and IORefs
> Hal Daume III wrote: > > You can't. [...] > > Well, you can, but only for CAFs. This idiom/hack is used > quite happily throughout GHC, HOpenGL, H/Direct, ... I think "quite happily" is a bit strong ;-) We'd much rather have a safe way to do what is really quite a reasonable thing. Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO and IORefs
> At 2002-11-18 11:05, Sven Panne wrote: > > >global :: a -> IORef a > >global a = unsafePerformIO (newIORef a) > > This is useful, you can do this with it: > > ref = global Nothing > > convert :: a -> IO b > convert a = do > writeIORef ref (Just a) > Just b <- readIORef ref > return b This particular "flexibility" provided by unsafePerformIO is actually documented... http://www.haskell.org/ghc/docs/latest/html/base/System.IO.Unsafe.html#u nsafePerformIO Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO and IORefs
Yes, there are several reasons for having UNSAFE in the name. :-) -- Lennart Ashley Yakeley wrote: At 2002-11-18 11:05, Sven Panne wrote: global :: a -> IORef a global a = unsafePerformIO (newIORef a) This is useful, you can do this with it: ref = global Nothing convert :: a -> IO b convert a = do writeIORef ref (Just a) Just b <- readIORef ref return b ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO and IORefs
At 2002-11-18 11:05, Sven Panne wrote: >global :: a -> IORef a >global a = unsafePerformIO (newIORef a) This is useful, you can do this with it: ref = global Nothing convert :: a -> IO b convert a = do writeIORef ref (Just a) Just b <- readIORef ref return b -- Ashley Yakeley, Seattle WA ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO and IORefs
On Mon, Nov 18, 2002 at 10:36:05AM -0800, Hal Daume III wrote: > You can't. CSE (common subexpression elimination) will replace any > occurances of 'newState 0' in a function body with the same value. > > In short: don't use upIO :) Sorry, cannot resist to pour a little salt onto the wound :) [232]% grep global ghc/compiler/utils/Util.lhs , global global :: a -> IORef a global a = unsafePerformIO (newIORef a) [233]% ghc/compiler/HsVersions.h: [...] #ifdef __GLASGOW_HASKELL__ #define GLOBAL_VAR(name,value,ty) \ name = Util.global (value) :: IORef (ty); \ {-# NOINLINE name #-} #endif [237]% grep -r GLOBAL_VAR ghc/compiler | wc -l 90 Muahahah... ;-P Cheers, Michael ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO and IORefs
Hal Daume III wrote: > You can't. [...] Well, you can, but only for CAFs. This idiom/hack is used quite happily throughout GHC, HOpenGL, H/Direct, ... Slightly modified stuff from GHC's sources: -- global variables in Haskell :-) global :: a -> IORef a global a = unsafePerformIO (newIORef a) #define GLOBAL_VAR(name,value,ty) \ name :: IORef (ty) ; \ name = global (value) ; \ {-# NOINLINE name #-} -- examples GLOBAL_VAR(counter, 0, Int) GLOBAL_VAR(flag, False, Bool) Cheers, S. ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO and IORefs
You can't. CSE (common subexpression elimination) will replace any occurances of 'newState 0' in a function body with the same value. In short: don't use upIO :) If I'm wrong, someone will correct me. But expect a few "what are you trying to do" email messages or people suggesting implicit paremeters or monad wrappers (in fact, count this as the first of said emails). - Hal -- Hal Daume III "Computer science is no more about computers| [EMAIL PROTECTED] than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume On Mon, 18 Nov 2002, Nicolas Oury wrote: > I want to write something like > > type State a = IORef a > > newState :: a -> State a > newState v = unsafePerformIO (newIORef v) > > > But I don't want the compileer to inline this nor to inline any > application of this. > > {#NOINLINE newState#} > > But how can I stop this function to be inlined when applied for example : > > let x = newState 0 in > {... code where x is used twice ...} > > How to be sure that x isn't inlined and that all occurences of x are > pointing to the same memory place ? > > Best regards, > Nicolas Oury > > ___ > Glasgow-haskell-users mailing list > [EMAIL PROTECTED] > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO
> [...] > > > > As for sharing, we currently don't provide any guarnatees, > although we > > should. It is currently the case that if you write > > > > a = unsafePerformIO (putStr "hello") > > b = unsafePerformIO (putStr "hello") > > > > and both a and b are evaluated, then you may get either one or two > > "hello"s on stdout. You can currently make things more > deterministic by > > (a) adding NOINLINE pragmas for a and b, and (b) using the > flag -fno-cse > > to disable common sub-expression elimination. Then you'll > get exactly > > two instances of "hello" on stdout, although we won't guarantee that > > behaviour for ever. At some point we'll fix it so that > unsafePerformIO > > applications are never duplicated or coalesced. > > > Are there any (short) examples available where using of > unsafePerformIO > leads to unexpected behaviour, > especially an example with the terms a and b from above? I don't have any examples to hand, but you ought to be able to make one up without too much difficulty. You just need two identical bindings such as in the example above, and compile with -O. Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO
- Original Message - From: "Simon Marlow" <[EMAIL PROTECTED]> Sent: Tuesday, September 24, 2002 2:58 PM Subject: RE: unsafePerformIO [...] > As for sharing, we currently don't provide any guarnatees, although we > should. It is currently the case that if you write > > a = unsafePerformIO (putStr "hello") > b = unsafePerformIO (putStr "hello") > > and both a and b are evaluated, then you may get either one or two > "hello"s on stdout. You can currently make things more deterministic by > (a) adding NOINLINE pragmas for a and b, and (b) using the flag -fno-cse > to disable common sub-expression elimination. Then you'll get exactly > two instances of "hello" on stdout, although we won't guarantee that > behaviour for ever. At some point we'll fix it so that unsafePerformIO > applications are never duplicated or coalesced. Are there any (short) examples available where using of unsafePerformIO leads to unexpected behaviour, especially an example with the terms a and b from above? with best regards, David - JWGU Frankfurt ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO
Koen Claessen <[EMAIL PROTECTED]> writes: > However, I for example have no idea what happens when unsafely > executing something that throws exceptions, performs a forkIO, > something that uses MVar's, etc. I won't dare to try to characterize the difference exactly but you should expect very different behaviour between Hugs and GHC when using unsafePerformIO with threads and exceptions. The Hugs version of unsafePerformIO isn't intended to receive as much abuse as the GHC version whereas the GHC version has been (ab)used by large numbers of people. -- Alastair ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO
Koen Based on this info, how would you like to write the notes you would like to see on unsafePerformIO? The starting point is at http://haskell.cs.yale.edu/ghc/docs/latest/html/base/GHC.IOBase.html#uns afePerformIO If you write the notes, we'll check their veracity and add them. We'll do the formatting too! Simon | -Original Message- | From: Simon Marlow [mailto:[EMAIL PROTECTED]] | Sent: 24 September 2002 13:59 | To: Koen Claessen; [EMAIL PROTECTED] | Subject: RE: unsafePerformIO | | > But it is a fact that many of us have at least some idea of | > what happens "under the hood" when we use unsafePerformIO. | > This is also described in your paper "Stretching the storage | > manager: weak pointers and stable names in Haskell". | > | > However, I for example have no idea what happens when | > unsafely executing something that throws exceptions, | > performs a forkIO, something that uses MVar's, etc. | | Exceptions: an exception raised by the computation inside | unsafePerformIO will be propagated to the enclosing expression, as per | the normal semantics for imprecise exceptions. The exception raised by | an application of unsafePerformIO may of course also be imprecise; | consider 'unsafePerformIO $ (1/0 + error "foo") `seq` return ()'. | | The behaviour of forkIO and other side-effecting operations inside | unsafePerforIO can I think be explained by the following statement: if | an expression "unsafePerformIO e" has been reduced to head normal form, | then all the I/O computations in e have been performed. The exact | timing of the evaluation is underspecified, just as any other expression | in Haskell. However, if you're using unsafePerformIO with real side | effects, then I suspect that what you're doing is highly dodgy and you | should find another way to do it :-) | | Does that help? | | As for sharing, we currently don't provide any guarnatees, although we | should. It is currently the case that if you write | | a = unsafePerformIO (putStr "hello") | b = unsafePerformIO (putStr "hello") | | and both a and b are evaluated, then you may get either one or two | "hello"s on stdout. You can currently make things more deterministic by | (a) adding NOINLINE pragmas for a and b, and (b) using the flag -fno-cse | to disable common sub-expression elimination. Then you'll get exactly | two instances of "hello" on stdout, although we won't guarantee that | behaviour for ever. At some point we'll fix it so that unsafePerformIO | applications are never duplicated or coalesced. | | If you're interested in when unsafePerformIO is "safe" to use, see: | | http://www.haskell.org/pipermail/glasgow-haskell-users/2002-July/003683. | html | | (and see my followups for an alternative view). | | Cheers, | Simon | ___ | Glasgow-haskell-users mailing list | [EMAIL PROTECTED] | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO
> But it is a fact that many of us have at least some idea of > what happens "under the hood" when we use unsafePerformIO. > This is also described in your paper "Stretching the storage > manager: weak pointers and stable names in Haskell". > > However, I for example have no idea what happens when > unsafely executing something that throws exceptions, > performs a forkIO, something that uses MVar's, etc. Exceptions: an exception raised by the computation inside unsafePerformIO will be propagated to the enclosing expression, as per the normal semantics for imprecise exceptions. The exception raised by an application of unsafePerformIO may of course also be imprecise; consider 'unsafePerformIO $ (1/0 + error "foo") `seq` return ()'. The behaviour of forkIO and other side-effecting operations inside unsafePerforIO can I think be explained by the following statement: if an expression "unsafePerformIO e" has been reduced to head normal form, then all the I/O computations in e have been performed. The exact timing of the evaluation is underspecified, just as any other expression in Haskell. However, if you're using unsafePerformIO with real side effects, then I suspect that what you're doing is highly dodgy and you should find another way to do it :-) Does that help? As for sharing, we currently don't provide any guarnatees, although we should. It is currently the case that if you write a = unsafePerformIO (putStr "hello") b = unsafePerformIO (putStr "hello") and both a and b are evaluated, then you may get either one or two "hello"s on stdout. You can currently make things more deterministic by (a) adding NOINLINE pragmas for a and b, and (b) using the flag -fno-cse to disable common sub-expression elimination. Then you'll get exactly two instances of "hello" on stdout, although we won't guarantee that behaviour for ever. At some point we'll fix it so that unsafePerformIO applications are never duplicated or coalesced. If you're interested in when unsafePerformIO is "safe" to use, see: http://www.haskell.org/pipermail/glasgow-haskell-users/2002-July/003683. html (and see my followups for an alternative view). Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO
Simon Peyton-Jones wrote: | The actions performed by unsafePerformIO are simply | done at some entirely unpredictable time, perhaps | interleaved with actions on the main execution path. But it is a fact that many of us have at least some idea of what happens "under the hood" when we use unsafePerformIO. This is also described in your paper "Stretching the storage manager: weak pointers and stable names in Haskell". However, I for example have no idea what happens when unsafely executing something that throws exceptions, performs a forkIO, something that uses MVar's, etc. It would be nice to see what happens in such a case, and at least a document that informally describes what happens. This includes issues such as loss of sharing because of inlining, etc. "unsafePerformIO" is the best thing since sliced bread for someone who wants to add stuff to the compiler without changing the compiler. The usefulness/portability at the moment is limited since nobody "dares" to say what is going on. /Koen. ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO
The actions performed by unsafePerformIO are simply done at some entirely unpredictable time, perhaps interleaved with actions on the main execution path. The formal semantics in the notes doesn't have a good way to express that because the purely-functional part is given a denotational semantics... yet unsafePerformIO can occur in the middle of that. So it's tiresome to characterise in theory, and hard to predict in practice. You should only use it when the state it is fiddling with is well partitioned. Simon | -Original Message- | From: David Sabel [mailto:[EMAIL PROTECTED]] | Sent: 20 September 2002 13:48 | To: Simon Peyton-Jones; [EMAIL PROTECTED] | Subject: unsafePerformIO | | In read your paper ""Tackling the Awkward Squad: monadic input / output, | concurrency, exceptions, and foreign-language calls in Haskell", and have | a question about unsafePerformIO. | | In your operational semantic of the IO-Monad you tell nothing about, how | 'unsafe' IO actions are performed, is there another paper / documentation | about | this available, or can you - or someone else - give me a review about that? | | David | JWGU Frankfurt | ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO
I'm not sure of a reference, the basic idea is this: IO a is represented by the pair (RealWorld, a) (unboxed, really but whatever) When an IO action is run (via main), a RealWorld state is provided by the compiler and passes it around. When you do unsafePerformIO, the compiler conjures up some value of type RealWorld to use. It is unsafe because it doesn't guarentee the relative order of IO actions. Of course, someone correct me if I'm mistaken. - Hal -- Hal Daume III "Computer science is no more about computers| [EMAIL PROTECTED] than astronomy is about telescopes." -Dijkstra | www.isi.edu/~hdaume On Fri, 20 Sep 2002, David Sabel wrote: > In read your paper ""Tackling the Awkward Squad: monadic input / output, > concurrency, exceptions, and foreign-language calls in Haskell", and have > a question about unsafePerformIO. > > In your operational semantic of the IO-Monad you tell nothing about, how > 'unsafe' IO actions are performed, is there another paper / documentation > about > this available, or can you - or someone else - give me a review about that? > > David > JWGU Frankfurt > > > ___ > Glasgow-haskell-users mailing list > [EMAIL PROTECTED] > http://www.haskell.org/mailman/listinfo/glasgow-haskell-users > ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO around FFI calls
> > That's a nice succinct way to describe it. Another way, which boils > > down to the same thing but which is a little more concrete, is to > > ask: > > > - Does the function's result depend only on the values of its > > arguments? > > I have two problems with this alternative test: > > 1) It is sometimes slightly stricter test than necessary. > >Consider a hypothetical pair of C functions > > Foo toFoo(int); > int fromFoo(Foo); > >which satisfy the property > > fromFoo(toFoo(x)) == x > >but such that the result of toFoo does not depend on its argument. >(Perhaps toFoo allocates some memory in which to stores its result >and returns a pointer to that memory.) > >The function's result does vary independently of its values so it >fails your test. > >But if toFoo/fromFoo are the only functions on Foo, then we could >obviously have implemented the same API in Haskell with the aid of >newtype so it passes my test. Ok, if we're going to nit pick :) When talking about equality you have to restrict that to "observable equivalence" in the context of whatever abstract types you're dealing with. If a function always returns observably equivalent results when given observably equivalent arguments, then it is "safe". For example, toFoo would not be safe if you can test for equality between pointers. But if all you can do is convert it back using fromFoo, then you're ok. > 2) It fails to recognise the fact that IO actions have side effects. Well, side effects are usually only visible in the IO monad so that's ok. In your free() example, the result is either () or _|_, so the function does depend on more than just the value of the argument. I think the definition holds (but only just). For example, we normally consider a function which uses some temporary allocation on the C heap as "safe" to use from unsafePerformIO. But its side effect is visible from the IO monad by inspecting the C heap pointer. Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO around FFI calls
> That's a nice succinct way to describe it. Another way, which boils > down to the same thing but which is a little more concrete, is to > ask: > - Does the function's result depend only on the values of its > arguments? I have two problems with this alternative test: 1) It is sometimes slightly stricter test than necessary. Consider a hypothetical pair of C functions Foo toFoo(int); int fromFoo(Foo); which satisfy the property fromFoo(toFoo(x)) == x but such that the result of toFoo does not depend on its argument. (Perhaps toFoo allocates some memory in which to stores its result and returns a pointer to that memory.) The function's result does vary independently of its values so it fails your test. But if toFoo/fromFoo are the only functions on Foo, then we could obviously have implemented the same API in Haskell with the aid of newtype so it passes my test. 2) It fails to recognise the fact that IO actions have side effects. For example, the C library function 'free' always returns the same result (i.e., '()') but it's a bad idea to call free twice on the same argument. One could argue that the side effect is part of the result because IO actions return a modified world but only a long term functional programmer would think like that so it doesn't help the man in the street. (In fact, IIRC, the Concurrent Haskell semantics doesn't use the state-passing explanation so you don't even see side effects reflected as changes in the returned world state.) -- Alastair Reid [EMAIL PROTECTED] Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/ ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
RE: unsafePerformIO around FFI calls
> Hal Daume <[EMAIL PROTECTED]> writes: > > I'm curious exactly what is "safe" and what is "unsafe" to wrap > > unsafePerformIO around when it comes to FFI calls. > > Here's a simple test: > > Could you imagine an alternative implementation of the same API in > pure Haskell? (Don't consider efficiency or effort required to write > the implementation, just whether it can be done.) > > If so, then it is ok to use unsafePerformIO and the ffi to implement > the API instead. > > If it fails that test, it is incredibly unlikely that it is ok and a > proof that it is ok is likely to be pretty complex - maybe worth a > PLDI paper or some such. That's a nice succinct way to describe it. Another way, which boils down to the same thing but which is a little more concrete, is to ask: - Does the function's result depend only on the values of its arguments? (obviously only makes sense for a top-level IO function which you want to wrap in unsafePerformIO - for a non-top-level function or expression just replace 'arguments' with 'arguments and free variables'). Cheers, Simon ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: unsafePerformIO around FFI calls
Hal Daume <[EMAIL PROTECTED]> writes: > I'm curious exactly what is "safe" and what is "unsafe" to wrap > unsafePerformIO around when it comes to FFI calls. Here's a simple test: Could you imagine an alternative implementation of the same API in pure Haskell? (Don't consider efficiency or effort required to write the implementation, just whether it can be done.) If so, then it is ok to use unsafePerformIO and the ffi to implement the API instead. If it fails that test, it is incredibly unlikely that it is ok and a proof that it is ok is likely to be pretty complex - maybe worth a PLDI paper or some such. -- Alastair Reid [EMAIL PROTECTED] Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/ ___ Glasgow-haskell-users mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/glasgow-haskell-users