New type of expressions containing (error ...) includes noisy implicit parameter

Prelude> let myList = [1, 2, 3 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList myList :: [Integer] Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer] This is on by default and insofar as I've been able to try, it's avoidable in a default GHCi 8.0 REPL session. I'm glad I caught this before our book goes to print in a couple months. We'd managed to avoid talking about implicit parameters in 1,100+ pages of book but now we're forced to acknowledge their existence in the 4th of 32 chapters. This slipped past the radar more stealthily than the earlier stages of BBP did for 7.10. I was hearing about BBP on the GHC Trac pretty early on for months on end. Was the thinking that people still used implicit parameters for anything or taught them? On the one hand, this is a nice change and something I personally attempted (and failed) to make easier in GHC 7.10. The implementation making the types noisy rankles and didn't seem necessary when I investigated it between 7.8 and 7.10. Could you warn us when (educationally relevant?) stuff like this is coming down the pipe before the RC please? Ideally during the design phase. I think this was discussed as part of FTP to avoid future debacles. This isn't just a pedagogical problem, this is a UX problem. The users don't _care_ that call stack information is being carried around. Why would they? It happens without any mention in the types in almost every other programming language. --- Chris Allen

Christopher Allen
Prelude> let myList = [1, 2, 3 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList myList :: [Integer] Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
...
This isn't just a pedagogical problem, this is a UX problem. The users don't _care_ that call stack information is being carried around. Why would they? It happens without any mention in the types in almost every other programming language.
Well, in the case of implicit call stacks users arguably *need* to care whether call stack information is carried around: you only get call stack information when you explicit request request one. This is one of the limitations of the implicit callstack mechanism. That being said, the example that you offer is a bit suspicious to the point where I suspect it's a bug. As far as I know, the solver should not introduce new callstack constraints: if a CallStack constraint doesn't exist in the available context the solver should simply satisfy it with an empty callstack and that should be the end of it (Eric, correct me if I'm wrong). Indeed, 7.10.2, which also had an early version of implicit callstack support, did exactly this. I haven't yet looked any further into what may have changed, but I have opened #11573 to track this. Thanks for pointing this out. Cheers, - Ben

On Sat, Feb 13, 2016, at 01:25, Ben Gamari wrote:
Christopher Allen
writes: Prelude> let myList = [1, 2, 3 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList myList :: [Integer] Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
...
This isn't just a pedagogical problem, this is a UX problem. The users don't _care_ that call stack information is being carried around. Why would they? It happens without any mention in the types in almost every other programming language.
Well, in the case of implicit call stacks users arguably *need* to care whether call stack information is carried around: you only get call stack information when you explicit request request one. This is one of the limitations of the implicit callstack mechanism.
That being said, the example that you offer is a bit suspicious to the point where I suspect it's a bug. As far as I know, the solver should not introduce new callstack constraints: if a CallStack constraint doesn't exist in the available context the solver should simply satisfy it with an empty callstack and that should be the end of it (Eric, correct me if I'm wrong).
Indeed, 7.10.2, which also had an early version of implicit callstack support, did exactly this. I haven't yet looked any further into what may have changed, but I have opened #11573 to track this.
The inferred CallStack is not a bug, it was added to fix #10845. The problem is that in a function like foo :: HasCallStack => ... foo x = let bar y = undefined in bar x we *need* to infer a CallStack for bar (due to the structure of the constraint solver) in order to link foo's CallStack to undefined. Currently, this extends to inferring CallStacks for top-level binders without explicit type signatures. Pedagogic concerns aside, I don't think this is a big deal as it's standard practice to provide explicit signatures. But it wouldn't be hard to make an exception for top-level binders. What *is* a bug is that GHC shows the implicit parameter in the inferred signature. We don't expose those anymore in the CallStack API, instead we use a type synonym HasCallStack. GHC should infer HasCallStack constraints instead. Eric

On 13 February 2016 at 08:32, Christopher Allen
Prelude> let myList = [1, 2, 3 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList myList :: [Integer] Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
Yes, and I think perhaps an even more worrying problem here is that by adding the reference to undefined, myList went from being a thunk to being a function. That is, it will be re-evaluated each time it it used. I made a ticket about this: https://ghc.haskell.org/trac/ghc/ticket/11383 Cheers Simon
This is on by default and insofar as I've been able to try, it's avoidable in a default GHCi 8.0 REPL session. I'm glad I caught this before our book goes to print in a couple months. We'd managed to avoid talking about implicit parameters in 1,100+ pages of book but now we're forced to acknowledge their existence in the 4th of 32 chapters.
This slipped past the radar more stealthily than the earlier stages of BBP did for 7.10. I was hearing about BBP on the GHC Trac pretty early on for months on end. Was the thinking that people still used implicit parameters for anything or taught them? On the one hand, this is a nice change and something I personally attempted (and failed) to make easier in GHC 7.10. The implementation making the types noisy rankles and didn't seem necessary when I investigated it between 7.8 and 7.10.
Could you warn us when (educationally relevant?) stuff like this is coming down the pipe before the RC please? Ideally during the design phase. I think this was discussed as part of FTP to avoid future debacles.
This isn't just a pedagogical problem, this is a UX problem. The users don't _care_ that call stack information is being carried around. Why would they? It happens without any mention in the types in almost every other programming language.
--- Chris Allen
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

But that is a consequence of call stacks being implemented by
threading a parameter through the calls, not of the fact that it shows
up in the type. Without the change in type, the programmer wouldn't be
informed there is any difference without looking at the core.
In other words, this gives one reason why users _do_ care that stack
information is being carried around, and might want to see it in the
type; it can have a runtime performance impact (and likely not just
for CAFs).
-- Dan
On Mon, Feb 15, 2016 at 5:12 AM, Simon Marlow
On 13 February 2016 at 08:32, Christopher Allen
wrote: Prelude> let myList = [1, 2, 3 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList myList :: [Integer] Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
Yes, and I think perhaps an even more worrying problem here is that by adding the reference to undefined, myList went from being a thunk to being a function. That is, it will be re-evaluated each time it it used. I made a ticket about this: https://ghc.haskell.org/trac/ghc/ticket/11383
Cheers Simon
This is on by default and insofar as I've been able to try, it's avoidable in a default GHCi 8.0 REPL session. I'm glad I caught this before our book goes to print in a couple months. We'd managed to avoid talking about implicit parameters in 1,100+ pages of book but now we're forced to acknowledge their existence in the 4th of 32 chapters.
This slipped past the radar more stealthily than the earlier stages of BBP did for 7.10. I was hearing about BBP on the GHC Trac pretty early on for months on end. Was the thinking that people still used implicit parameters for anything or taught them? On the one hand, this is a nice change and something I personally attempted (and failed) to make easier in GHC 7.10. The implementation making the types noisy rankles and didn't seem necessary when I investigated it between 7.8 and 7.10.
Could you warn us when (educationally relevant?) stuff like this is coming down the pipe before the RC please? Ideally during the design phase. I think this was discussed as part of FTP to avoid future debacles.
This isn't just a pedagogical problem, this is a UX problem. The users don't _care_ that call stack information is being carried around. Why would they? It happens without any mention in the types in almost every other programming language.
--- Chris Allen
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

On 15 February 2016 at 13:40, Dan Doel
But that is a consequence of call stacks being implemented by threading a parameter through the calls, not of the fact that it shows up in the type. Without the change in type, the programmer wouldn't be informed there is any difference without looking at the core.
I'm not suggesting that the parameter should be hidden in the type! I agree that would be much worse. No, I'm arguing that it was bad that we lost sharing just by using undefined (or error). If adding a call to error somewhere in your code changes its asymptotic performance, that's at the very least surprising. Apologies for diverting the discussion. I also think it's potentially bad from an educational point of view that error/undefined have these non-standard types, in fact I argued against using implicit call stacks in other functions in base for this reason (amongst others), and fortunately we've limited it to just these. Cheers Simon In other words, this gives one reason why users _do_ care that stack
information is being carried around, and might want to see it in the type; it can have a runtime performance impact (and likely not just for CAFs).
-- Dan
On 13 February 2016 at 08:32, Christopher Allen
wrote: Prelude> let myList = [1, 2, 3 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList myList :: [Integer] Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
Yes, and I think perhaps an even more worrying problem here is that by adding the reference to undefined, myList went from being a thunk to being a function. That is, it will be re-evaluated each time it it used. I made a ticket about this: https://ghc.haskell.org/trac/ghc/ticket/11383
Cheers Simon
This is on by default and insofar as I've been able to try, it's
avoidable
in a default GHCi 8.0 REPL session. I'm glad I caught this before our book goes to print in a couple months. We'd managed to avoid talking about implicit parameters in 1,100+ pages of book but now we're forced to acknowledge their existence in the 4th of 32 chapters.
This slipped past the radar more stealthily than the earlier stages of BBP did for 7.10. I was hearing about BBP on the GHC Trac pretty early on for months on end. Was the thinking that people still used implicit
for anything or taught them? On the one hand, this is a nice change and something I personally attempted (and failed) to make easier in GHC 7.10. The implementation making the types noisy rankles and didn't seem necessary when I investigated it between 7.8 and 7.10.
Could you warn us when (educationally relevant?) stuff like this is coming down the pipe before the RC please? Ideally during the design phase. I
On Mon, Feb 15, 2016 at 5:12 AM, Simon Marlow
wrote: parameters think this was discussed as part of FTP to avoid future debacles.
This isn't just a pedagogical problem, this is a UX problem. The users don't _care_ that call stack information is being carried around. Why would they? It happens without any mention in the types in almost every other programming language.
--- Chris Allen
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
participants (5)
-
Ben Gamari
-
Christopher Allen
-
Dan Doel
-
Eric Seidel
-
Simon Marlow