Re: Using DeepSeq for exception ordering
On 12/11/2012 16:56, Simon Hengel wrote: Did you try -fpedantic-bottoms? I just tried. The exception (or seq?) is still optimized away. Here is what I tried: -- file Foo.hs import Control.Exception import Control.DeepSeq main = evaluate (('a' : undefined) `deepseq` return () :: IO ()) $ ghc -fforce-recomp -fpedantic-bottoms -O Foo.hs ./Foo echo bar [1 of 1] Compiling Main ( Foo.hs, Foo.o ) Linking Foo ... bar Sounds like a bug, -fpedantic-bottoms should work here. Please open a ticket. Cheers, Simon ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
Sounds like a bug, -fpedantic-bottoms should work here. Please open a ticket. done [1]. [1] http://hackage.haskell.org/trac/ghc/ticket/7411 ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
Did you try -fpedantic-bottoms? Cheers, Simon On 08/11/2012 19:16, Edward Z. Yang wrote: It looks like the optimizer is getting confused when the value being evaluated is an IO action (nota bene: 'evaluate m' where m :: IO a is pretty odd, as far as things go). File a bug? Cheers, Edward Excerpts from Albert Y. C. Lai's message of Thu Nov 08 10:04:15 -0800 2012: On 12-11-08 01:01 PM, Nicolas Frisby wrote: And the important observation is: all of them throw A if interpreted in ghci or compiled without -O, right? Yes. ___ 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: Using DeepSeq for exception ordering
On 12-11-12 11:34 AM, Simon Marlow wrote: Did you try -fpedantic-bottoms? Interesting option. And furthermore its doc refers to -fno-state-hack, too. import Control.DeepSeq import Control.Exception main = do evaluate (('a' : error A) `deepseq` putStrLn hi) throwIO (userError B) -O -fpedantic-bottoms = B -O -fno-state-hack = A -O both = A 7.4.2, linux 32-bit x86 ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
Did you try -fpedantic-bottoms? I just tried. The exception (or seq?) is still optimized away. Here is what I tried: -- file Foo.hs import Control.Exception import Control.DeepSeq main = evaluate (('a' : undefined) `deepseq` return () :: IO ()) $ ghc -fforce-recomp -fpedantic-bottoms -O Foo.hs ./Foo echo bar [1 of 1] Compiling Main ( Foo.hs, Foo.o ) Linking Foo ... bar Cheers, Simon ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
Hi Edward, thanks a lot for your reply. rnf can be thought of a function which produces a thunk (for unit) which, when forced, fully evaluates the function. With this in hand, it's pretty clear how to use evaluate to enforce ordering: evaluate (rnf ('a': throw exceptionA)) So if I understand correctly, then if I have evaluate (x_1 `seq` x_2 `seq` x_3 `seq` ... `seq` x_n) throwIO exceptionB it is guaranteed that exceptionB can only happens if none of the xs are exceptional. I was just going to say that I can give at least one counterexample where this does not hold: evaluate (('a' : undefined) `deepseq` return () :: IO ()) throwIO exceptionB But then I realized that here exceptionA is optimized away altogether. For me this smells like a bug. Is this related to [1]? Cheers, Simon [1] http://hackage.haskell.org/trac/ghc/ticket/2273 ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
On 12-11-08 07:12 AM, Simon Hengel wrote: I was just going to say that I can give at least one counterexample where this does not hold: evaluate (('a' : undefined) `deepseq` return () :: IO ()) throwIO exceptionB But then I realized that here exceptionA is optimized away altogether. For me this smells like a bug. Is this related to [1]? [1] http://hackage.haskell.org/trac/ghc/ticket/2273 Interesting. A few more tests (all GHC 7.4.2, linux, x86 32-bit, use ghc -O to compile): The following cases throw A: import Control.DeepSeq import Control.Exception main = do evaluate (('a' : error A) `deepseq` return () :: Maybe ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` True) throwIO (userError B) main = do x - evaluate (('a' : error A) `deepseq` putStrLn hi) x throwIO (userError B) The following cases throw B: main = do evaluate (('a' : error A) `deepseq` return () :: IO ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` putStrLn hi) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` getLine) throwIO (userError B) ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
And the important observation is: all of them throw A if interpreted in ghci or compiled without -O, right? On Thu, Nov 8, 2012 at 11:24 AM, Albert Y. C. Lai tre...@vex.net wrote: On 12-11-08 07:12 AM, Simon Hengel wrote: I was just going to say that I can give at least one counterexample where this does not hold: evaluate (('a' : undefined) `deepseq` return () :: IO ()) throwIO exceptionB But then I realized that here exceptionA is optimized away altogether. For me this smells like a bug. Is this related to [1]? [1] http://hackage.haskell.org/**trac/ghc/ticket/2273http://hackage.haskell.org/trac/ghc/ticket/2273 Interesting. A few more tests (all GHC 7.4.2, linux, x86 32-bit, use ghc -O to compile): The following cases throw A: import Control.DeepSeq import Control.Exception main = do evaluate (('a' : error A) `deepseq` return () :: Maybe ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` True) throwIO (userError B) main = do x - evaluate (('a' : error A) `deepseq` putStrLn hi) x throwIO (userError B) The following cases throw B: main = do evaluate (('a' : error A) `deepseq` return () :: IO ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` putStrLn hi) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` getLine) throwIO (userError B) __**_ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.**org Glasgow-haskell-users@haskell.org http://www.haskell.org/**mailman/listinfo/glasgow-**haskell-usershttp://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: Using DeepSeq for exception ordering
On 12-11-08 01:01 PM, Nicolas Frisby wrote: And the important observation is: all of them throw A if interpreted in ghci or compiled without -O, right? Yes. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
It looks like the optimizer is getting confused when the value being evaluated is an IO action (nota bene: 'evaluate m' where m :: IO a is pretty odd, as far as things go). File a bug? Cheers, Edward Excerpts from Albert Y. C. Lai's message of Thu Nov 08 10:04:15 -0800 2012: On 12-11-08 01:01 PM, Nicolas Frisby wrote: And the important observation is: all of them throw A if interpreted in ghci or compiled without -O, right? Yes. ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
Is this related to imprecise exceptions? http://research.microsoft.com/en-us/um/people/simonpj/papers/imprecise-exn.htm Antoine On Thu, Nov 8, 2012 at 12:01 PM, Nicolas Frisby nicolas.fri...@gmail.comwrote: And the important observation is: all of them throw A if interpreted in ghci or compiled without -O, right? On Thu, Nov 8, 2012 at 11:24 AM, Albert Y. C. Lai tre...@vex.net wrote: On 12-11-08 07:12 AM, Simon Hengel wrote: I was just going to say that I can give at least one counterexample where this does not hold: evaluate (('a' : undefined) `deepseq` return () :: IO ()) throwIO exceptionB But then I realized that here exceptionA is optimized away altogether. For me this smells like a bug. Is this related to [1]? [1] http://hackage.haskell.org/**trac/ghc/ticket/2273http://hackage.haskell.org/trac/ghc/ticket/2273 Interesting. A few more tests (all GHC 7.4.2, linux, x86 32-bit, use ghc -O to compile): The following cases throw A: import Control.DeepSeq import Control.Exception main = do evaluate (('a' : error A) `deepseq` return () :: Maybe ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` True) throwIO (userError B) main = do x - evaluate (('a' : error A) `deepseq` putStrLn hi) x throwIO (userError B) The following cases throw B: main = do evaluate (('a' : error A) `deepseq` return () :: IO ()) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` putStrLn hi) throwIO (userError B) main = do evaluate (('a' : error A) `deepseq` getLine) throwIO (userError B) __**_ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.**org Glasgow-haskell-users@haskell.org http://www.haskell.org/**mailman/listinfo/glasgow-**haskell-usershttp://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 ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Re: Using DeepSeq for exception ordering
Hello Simon, I think the confusion here is focused on what exactly it is that the NFData class offers: class NFData a where rnf :: a - () rnf can be thought of a function which produces a thunk (for unit) which, when forced, fully evaluates the function. With this in hand, it's pretty clear how to use evaluate to enforce ordering: evaluate (rnf ('a': throw exceptionA)) One could imagine defining: deepSeqEvaluate :: NFData a = a - IO () deepSeqEvaluate = evaluate . rnf In general, the right way to think about the semantics here is to distinguish between evaluation as an explicit effect (evaluate) and evaluation as a side effect of running IO (when you x `seq` return ()). They're distinct, and the latter doesn't give you ordering guarantees. This applies even when DeepSeq is involved. Cheers, Edward Excerpts from Simon Hengel's message of Wed Nov 07 05:49:21 -0800 2012: Hi, I'm puzzled whether it is feasible to use existing NFData instances for exception ordering. Here is some code that won't work: return $!! 'a' : throw exceptionA throwIO exceptionB Here GHC makes a non-deterministic choice between exceptionA and exceptionB. The reason is that the standard DeepSeq instances use `seq`, and `seq` does not help with exception ordering**. I tried several things (ghc-7.4.2 with -O2), and the following seems to order the exceptions for this particular case: (evaluate . force) ('a' : throw exceptionA) throwIO exceptionB But I'm a little bit worried that this may not hold in general, e.g. (return $!! 'a' : throw exceptionA) = evaluate throwIO exceptionB results in exceptionB. I think my main issue here is that I do not properly understand how seq and seq# (which is used by evaluate) do interact with each other. And how I can reason about code that uses both. The question is really whether it is somehow feasible to use existing NFData instances to order exceptions. Or would we need to define a separate type class + instances for that, e.g.: class DeepEvaluate a where deepEvaluate :: a - IO a deepEvaluate = evaluate instance DeepEvaluate Char where instance DeepEvaluate a = DeepEvaluate [a] where deepEvaluate = mapM deepEvaluate If you have any related ideas or thoughts, I'd love to hear about them. Cheers, Simon ** This is desired behavior, see the discussion at http://hackage.haskell.org/trac/ghc/ticket/5129 ___ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users