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. We checked after the previous thread where ($) occurred in the book. ($) is in the second chapter of the book, which is the first chapter of Haskell code. Now we have to hand-wave something completely impossible for them to understand (chapter 2 is expressions, types are chapter 5) or edit ($) out of the book until they can understand it. We can't write it completely out of the book because ($) gets used all over the place and we don't want encountering it to throw them off. --- Chris Allen

Just a clarification - the presence of that parameter does not say "I use
call stack" but rather "I need *a* call stack". This subtle difference
means that you do need to know about this due to how stacks work in GHC. If
you use error and then don't also add that constraint yourself to your
function, youll only see part of the stack. Hence it more than just UX
noise - I have a decision to make, and building a call stack gas a cost.
Also, is this RC2? I thought this was now changed to use constraint kinds
and type alias the implicit parameter behind a nicer API.
On Sat, 13 Feb 2016 8:51 am 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 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.
We checked after the previous thread where ($) occurred in the book. ($) is in the second chapter of the book, which is the first chapter of Haskell code. Now we have to hand-wave something completely impossible for them to understand (chapter 2 is expressions, types are chapter 5) or edit ($) out of the book until they can understand it. We can't write it completely out of the book because ($) gets used all over the place and we don't want encountering it to throw them off.
--- Chris Allen
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

subtle difference means that you do need to know about this due to how stacks work in GHC. If you use error and then don't also add that constraint yourself to your function, youll only see part of the stack.
It is unfortunate that the design forces this implementation detail on users trying to apply a plain old function. I updated my GHC 8.0.1 candidate, got this: $ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
changed to use constraint kinds and type alias the implicit parameter behind a nicer API.
Even if this has happened, we're still talking about the fourth chapter
which is prior to types, typeclasses, constraints - everything. None of
this means anything to a beginner being shown how to use undefined. The
book is trying to make sure _anyone_ can learn Haskell, it's not an
advanced DSLs book that introduces DataKinds.
The implementation is leaking all the way to the fourth chapter of a book
for complete beginners. Users will not be sympathetic when the
implementation elides information because the user failed to speak to the
nasal demons in the correct accent.
On Sat, Feb 13, 2016 at 3:04 AM, Oliver Charles
Just a clarification - the presence of that parameter does not say "I use call stack" but rather "I need *a* call stack". This subtle difference means that you do need to know about this due to how stacks work in GHC. If you use error and then don't also add that constraint yourself to your function, youll only see part of the stack. Hence it more than just UX noise - I have a decision to make, and building a call stack gas a cost.
Also, is this RC2? I thought this was now changed to use constraint kinds and type alias the implicit parameter behind a nicer API.
On Sat, 13 Feb 2016 8:51 am 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]
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.
We checked after the previous thread where ($) occurred in the book. ($) is in the second chapter of the book, which is the first chapter of Haskell code. Now we have to hand-wave something completely impossible for them to understand (chapter 2 is expressions, types are chapter 5) or edit ($) out of the book until they can understand it. We can't write it completely out of the book because ($) gets used all over the place and we don't want encountering it to throw them off.
--- Chris Allen
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com

Il giorno 13 feb 2016, alle ore 10:15, Christopher Allen
ha scritto: subtle difference means that you do need to know about this due to how stacks work in GHC. If you use error and then don't also add that constraint yourself to your function, youll only see part of the stack.
It is unfortunate that the design forces this implementation detail on users trying to apply a plain old function.
I updated my GHC 8.0.1 candidate, got this:
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
changed to use constraint kinds and type alias the implicit parameter behind a nicer API.
Even if this has happened, we're still talking about the fourth chapter which is prior to types, typeclasses, constraints - everything. None of this means anything to a beginner being shown how to use undefined. The book is trying to make sure _anyone_ can learn Haskell, it's not an advanced DSLs book that introduces DataKinds.
The implementation is leaking all the way to the fourth chapter of a book for complete beginners. Users will not be sympathetic when the implementation elides information because the user failed to speak to the nasal demons in the correct accent.
Hi Christopher, I’m following your painful experience preparing the book for GHC 8.0, and I sympathize with you. Just a question: how do you manage the type of simple arithmetic expressions like 1 + 1? I mean, the type contains a constraint there. Prelude> :t 1 + 1 1 + 1 :: Num a => a I suppose that explaining “Num a =>” by saying “it says that the type must be a number” is easier because of assonance with the word, but is that really a difference? Note that this situation is much different from the issue about the type of ($): - Teaching ‘undefined’ to beginners is not essential. It’s use is waaay less common that ($), and it should be especially for beginners. Partial functions should be discouraged from the start, and maybe a slightly more difficult type can be the right way to make people learn to not use it. It’s use comes handy when explaining laziness, maybe. But you could obtain the same effect with a never-ending function, which is also theoretically more affine to the meaning of “bottom”. - The constraint explicitly mentions “CallStack” twice. Exactly like “Num”, I think it’s easy to handwave: “The 'blahblah =>' part says that the function needs to know the ‘call stack’, which is what you see printed when ‘undefined’ gets evaluated and the program exists”. So while I agree with you that this type is more difficult to explain, I think it’s much less of a problem than the new type of ($). If you don’t agree with any of these points please let me know. Regards, Nicola

On Sat, Feb 13, 2016 at 5:28 PM, Nicola Gigante
Il giorno 13 feb 2016, alle ore 10:15, Christopher Allen < cma@bitemyapp.com> ha scritto:
subtle difference means that you do need to know about this due to how stacks work in GHC. If you use error and then don't also add that constraint yourself to your function, youll only see part of the stack.
It is unfortunate that the design forces this implementation detail on users trying to apply a plain old function.
I updated my GHC 8.0.1 candidate, got this:
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
changed to use constraint kinds and type alias the implicit parameter behind a nicer API.
Even if this has happened, we're still talking about the fourth chapter which is prior to types, typeclasses, constraints - everything. None of this means anything to a beginner being shown how to use undefined. The book is trying to make sure _anyone_ can learn Haskell, it's not an advanced DSLs book that introduces DataKinds.
The implementation is leaking all the way to the fourth chapter of a book for complete beginners. Users will not be sympathetic when the implementation elides information because the user failed to speak to the nasal demons in the correct accent.
Hi Christopher, I’m following your painful experience preparing the book for GHC 8.0, and I sympathize with you.
Just a question: how do you manage the type of simple arithmetic expressions like 1 + 1? I mean, the type contains a constraint there.
Yeah That nails the problem well enough (for me) I use the 25 year old gofer http://blog.languager.org/2014/09/pugofer.html with its simple prelude precisely because Num, Eq, Show etc are too expensive (for me) early in teaching FP And the simple prelude is the typeclass-free prelude
Teaching ‘undefined’ to beginners is not essential.
Not from where I see. A very basic feature of my teaching is - "Stories types tell" (also patterns tell) - Combined with going between values and types eg What is the type of 2? Int Complementarily Give something whose type is Int? 2 So what is something whose type is a?

Here's what the GHCi session should look like.
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
If your readers are using :t they must already know about simple types like Integer, [], and, ->, so the new things are HasCallStack and =>. This is how I would explain them. => is just like -> except the compiler fills in the argument by itself. HasCallStack tells the compiler that the expression needs a call-stack because it might crash. So HasCallStack => [Integer] is a [Integer] that might crash and produce a stack-trace. I think the call-stacks are much less scary and confusing than type-classes in general, which you kind of have to deal with as soon as you talk about arithmetic. Eric

"What's a call stack?"
(I don't know what Chris' target audience is though)
On Sat, 13 Feb 2016 5:18 pm Eric Seidel
Here's what the GHCi session should look like.
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
If your readers are using :t they must already know about simple types like Integer, [], and, ->, so the new things are HasCallStack and =>. This is how I would explain them.
=> is just like -> except the compiler fills in the argument by itself. HasCallStack tells the compiler that the expression needs a call-stack because it might crash. So HasCallStack => [Integer] is a [Integer] that might crash and produce a stack-trace.
I think the call-stacks are much less scary and confusing than type-classes in general, which you kind of have to deal with as soon as you talk about arithmetic.
Eric _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

I don't have a copy of GHC 8 atm to test this with: is an expression like this now illegal? x :: Int x = undefined I.e. do you need to write: x :: HasCallStack => Int x = undefined Tom
El 13 feb 2016, a las 12:37, Oliver Charles
escribió: "What's a call stack?"
(I don't know what Chris' target audience is though)
On Sat, 13 Feb 2016 5:18 pm Eric Seidel
wrote: Here's what the GHCi session should look like. $ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
If your readers are using :t they must already know about simple types like Integer, [], and, ->, so the new things are HasCallStack and =>. This is how I would explain them.
=> is just like -> except the compiler fills in the argument by itself. HasCallStack tells the compiler that the expression needs a call-stack because it might crash. So HasCallStack => [Integer] is a [Integer] that might crash and produce a stack-trace.
I think the call-stacks are much less scary and confusing than type-classes in general, which you kind of have to deal with as soon as you talk about arithmetic.
Eric _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

amindfv@gmail.com writes:
I don't have a copy of GHC 8 atm to test this with: is an expression like this now illegal?
x :: Int x = undefined
This is still valid. The change in GHC 8.0 is merely that GHC will infer a CallStack constraint instead of solving it in-place if asked to infer a type for a let binding whose RHS demands a callstack. Cheers, - Ben

That looks much better! So if I use "error" in a function "f", I pass "f" to be used in a location without a stack trace, and the error condition occurs, what happens? Incomplete trace? -Will
On Feb 13, 2016, at 11:18, Eric Seidel
wrote: Prelude> :t myList' myList' :: HasCallStack => [Integer]

You'll get an incomplete trace starting at "f". On Sat, Feb 13, 2016, at 10:33, Will Yager wrote:
That looks much better!
So if I use "error" in a function "f", I pass "f" to be used in a location without a stack trace, and the error condition occurs, what happens? Incomplete trace?
-Will
On Feb 13, 2016, at 11:18, Eric Seidel
wrote: Prelude> :t myList' myList' :: HasCallStack => [Integer]

On Sat, Feb 13, 2016 at 09:18:07AM -0800, Eric Seidel wrote:
Here's what the GHCi session should look like.
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
What use case is satisfied by providing this information? How does it benefit the Haskell programmer? How do I use it?

Replying to a few here. Gigante:
Just a question: how do you manage the type of simple arithmetic expressions like 1 + 1? I mean, the type contains a constraint there. Prelude> :t 1 + 1 1 + 1 :: Num a => a
If your readers are using :t they must already know about simple types
Earlier versions of the book intentionally juked this or concreted the type of numbers to Integer, but HaskellForMac defenestrated that with the always-on type showing so now we've had an explanation along the lines you suggest for a few months now. We know how to adapt - we've tested the book extensively. What we need is the implementation not to expose irrelevant magic/noise in ways that could leak into the first chapter with Haskell code in it. Seidel: like Integer, [], and, ->, so the new things are HasCallStack and =>. You'd bloody think as we're careful when we introduce :t, but we get tickets from people using HaskellForMac[1] that get confused because they are shown the types of expressions too early. Now we're careful in how we introduce _any_ expressions. Fisking your attempt:
=> is just like -> except
They don't know what either of those things are or what they mean in the second chapter because this is the _first_ chapter with any Haskell code. They're just beginning to see how Haskell code might be kinda like the lambdas in the lambda calculus chapter.
the compiler fills in the argument by
We do explain what a compiler and interpreter are, but they won't know what it means for it to fill in an argument. They don't know why it needs to fill in an argument. Where did the argument come from?
HasCallStack tells the compiler
How? Why? Why do they need to care? What's a HasCallStack? Keep in mind they don't know types, typeclasses, or anything else.
that the expression needs a call-stack
Still don't know what a call, stack, or call-stack are.
because it might crash.
Why does that change the type? We can construct bottoms like `let x in x` that crash the program without changing the type.
So HasCallStack => [Integer] is a [Integer]
What makes this even more obnoxious is that when we finally do introduce typeclasses and constraints, we talk about constraining a _type variable_ and now you've baked this magic in they cannot possibly be explained at all in the book.
that might crash and produce a stack-trace
First bit they might pick up from context, they don't know what a stack trace is. Bonus round: when you explain things "from first principles", you can't duck the fact that it's actually a call graph when explaining a "stack" trace or call stack. Now you have to explain why/how it gets flattened from one representation into the other. Oliver had it when he said,
"What's a call stack?"
I don't have a copy of GHC 8 atm to test this with: is an expression like
They don't know what a stack, a call, or the combination thereof is. We had planned to address these issues in the (much later) chapters that cover profiling and errors. Because that's when they're relevant. This hasn't been relevant the entire span of the book. It _never_ mattered that you didn't get a stack trace from bottoms. In practice, does it suck? Sure! But they're not practitioners yet! I am (I use Haskell for my 9-5 and have done for a year and a half) and it still hasn't mattered to me. The only time I've really wanted a stack trace is when this mechanism would not have been available to me to begin with. Gamari / amindfv this now illegal?
x :: Int x = undefined
This is still valid. The change in GHC 8.0 is merely that GHC will infer a CallStack constraint instead of solving it in-place if asked to infer a type for a let binding whose RHS demands a callstack.
We have readers use the REPL _a lot_. Not only to load code but also free-standing expressions in the REPL when experimenting and learning. Type assignment in the REPL is noisy and we have to write around some pretty gnarly width limitations (40-60 cols). This breaks the examples where we're combining bottom and type inference to explore how terms and types interact. I am less disturbed by `HasCallStack =>` than I was by the inferred type of ($). I know designing around pedagogical limitations like this is tedious but imagine doing it for 900-1,200 pages (formatting varies) of tutorial and exercises, then getting unpleasant surprises right as the book is about to be done. Sorry about the messy thread all. [1]: http://haskellformac.com/ On Sat, Feb 13, 2016 at 1:48 PM, Bryan Richter wrote:
On Sat, Feb 13, 2016 at 09:18:07AM -0800, Eric Seidel wrote:
Here's what the GHCi session should look like.
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
What use case is satisfied by providing this information? How does it benefit the Haskell programmer? How do I use it?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com

Maybe it would be better to introduce _ rather than using undefined
for holes in programs. This sidesteps this issue, provides useful
information to guide the implementation and causes an error when code
is compiled so programs aren't unexpectedly partial.
It is perhaps not idiomatic to use undefined, even in development
these days. It is much easier (imo) to use holes and
-fdefer-type-errors.
'undefined' is nasty and has to be used with care; CallStacks exist as
a bit of a safety net. I've not read your book but I'm not convinced
it should be emphasised so much in the first chapters of an elementary
Haskell textbook.
On Sat, Feb 13, 2016 at 8:52 PM, Christopher Allen
Replying to a few here.
Gigante:
Just a question: how do you manage the type of simple arithmetic expressions like 1 + 1? I mean, the type contains a constraint there. Prelude> :t 1 + 1 1 + 1 :: Num a => a
Earlier versions of the book intentionally juked this or concreted the type of numbers to Integer, but HaskellForMac defenestrated that with the always-on type showing so now we've had an explanation along the lines you suggest for a few months now. We know how to adapt - we've tested the book extensively. What we need is the implementation not to expose irrelevant magic/noise in ways that could leak into the first chapter with Haskell code in it.
Seidel:
If your readers are using :t they must already know about simple types like Integer, [], and, ->, so the new things are HasCallStack and =>.
You'd bloody think as we're careful when we introduce :t, but we get tickets from people using HaskellForMac[1] that get confused because they are shown the types of expressions too early. Now we're careful in how we introduce _any_ expressions.
Fisking your attempt:
=> is just like -> except
They don't know what either of those things are or what they mean in the second chapter because this is the _first_ chapter with any Haskell code. They're just beginning to see how Haskell code might be kinda like the lambdas in the lambda calculus chapter.
the compiler fills in the argument by
We do explain what a compiler and interpreter are, but they won't know what it means for it to fill in an argument. They don't know why it needs to fill in an argument. Where did the argument come from?
HasCallStack tells the compiler
How? Why? Why do they need to care? What's a HasCallStack? Keep in mind they don't know types, typeclasses, or anything else.
that the expression needs a call-stack
Still don't know what a call, stack, or call-stack are.
because it might crash.
Why does that change the type? We can construct bottoms like `let x in x` that crash the program without changing the type.
So HasCallStack => [Integer] is a [Integer]
What makes this even more obnoxious is that when we finally do introduce typeclasses and constraints, we talk about constraining a _type variable_ and now you've baked this magic in they cannot possibly be explained at all in the book.
that might crash and produce a stack-trace
First bit they might pick up from context, they don't know what a stack trace is. Bonus round: when you explain things "from first principles", you can't duck the fact that it's actually a call graph when explaining a "stack" trace or call stack. Now you have to explain why/how it gets flattened from one representation into the other.
Oliver had it when he said,
"What's a call stack?"
They don't know what a stack, a call, or the combination thereof is. We had planned to address these issues in the (much later) chapters that cover profiling and errors. Because that's when they're relevant. This hasn't been relevant the entire span of the book. It _never_ mattered that you didn't get a stack trace from bottoms. In practice, does it suck? Sure! But they're not practitioners yet! I am (I use Haskell for my 9-5 and have done for a year and a half) and it still hasn't mattered to me. The only time I've really wanted a stack trace is when this mechanism would not have been available to me to begin with.
Gamari / amindfv
I don't have a copy of GHC 8 atm to test this with: is an expression like this now illegal?
x :: Int x = undefined
This is still valid. The change in GHC 8.0 is merely that GHC will infer a CallStack constraint instead of solving it in-place if asked to infer a type for a let binding whose RHS demands a callstack.
We have readers use the REPL _a lot_. Not only to load code but also free-standing expressions in the REPL when experimenting and learning. Type assignment in the REPL is noisy and we have to write around some pretty gnarly width limitations (40-60 cols). This breaks the examples where we're combining bottom and type inference to explore how terms and types interact.
I am less disturbed by `HasCallStack =>` than I was by the inferred type of ($).
I know designing around pedagogical limitations like this is tedious but imagine doing it for 900-1,200 pages (formatting varies) of tutorial and exercises, then getting unpleasant surprises right as the book is about to be done.
Sorry about the messy thread all.
[1]: http://haskellformac.com/
On Sat, Feb 13, 2016 at 1:48 PM, Bryan Richter wrote:
On Sat, Feb 13, 2016 at 09:18:07AM -0800, Eric Seidel wrote:
Here's what the GHCi session should look like.
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
What use case is satisfied by providing this information? How does it benefit the Haskell programmer? How do I use it?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

Holes and bottoms are wildly different. Bottoms are considerably more useful which I think you'd find if you ran down a list of examples and tried both in each circumstance. This would force even more rewriting than present circumstances.
'undefined' is nasty and has to be used with care
Ya, we tell them that. We also tell them that programs intended to be executed outside of a learning/development environment should be total (we explain totality and partiality). On Sat, Feb 13, 2016 at 3:08 PM, Matthew Pickering < matthewtpickering@gmail.com> wrote:
Maybe it would be better to introduce _ rather than using undefined for holes in programs. This sidesteps this issue, provides useful information to guide the implementation and causes an error when code is compiled so programs aren't unexpectedly partial.
It is perhaps not idiomatic to use undefined, even in development these days. It is much easier (imo) to use holes and -fdefer-type-errors.
'undefined' is nasty and has to be used with care; CallStacks exist as a bit of a safety net. I've not read your book but I'm not convinced it should be emphasised so much in the first chapters of an elementary Haskell textbook.
Replying to a few here.
Gigante:
Just a question: how do you manage the type of simple arithmetic expressions like 1 + 1? I mean, the type contains a constraint there. Prelude> :t 1 + 1 1 + 1 :: Num a => a
Earlier versions of the book intentionally juked this or concreted the type of numbers to Integer, but HaskellForMac defenestrated that with the always-on type showing so now we've had an explanation along the lines you suggest for a few months now. We know how to adapt - we've tested the book extensively. What we need is the implementation not to expose irrelevant magic/noise in ways that could leak into the first chapter with Haskell code in it.
Seidel:
If your readers are using :t they must already know about simple types like Integer, [], and, ->, so the new things are HasCallStack and =>.
You'd bloody think as we're careful when we introduce :t, but we get tickets from people using HaskellForMac[1] that get confused because they are shown the types of expressions too early. Now we're careful in how we introduce _any_ expressions.
Fisking your attempt:
=> is just like -> except
They don't know what either of those things are or what they mean in the second chapter because this is the _first_ chapter with any Haskell code. They're just beginning to see how Haskell code might be kinda like the lambdas in the lambda calculus chapter.
the compiler fills in the argument by
We do explain what a compiler and interpreter are, but they won't know what it means for it to fill in an argument. They don't know why it needs to fill in an argument. Where did the argument come from?
HasCallStack tells the compiler
How? Why? Why do they need to care? What's a HasCallStack? Keep in mind
don't know types, typeclasses, or anything else.
that the expression needs a call-stack
Still don't know what a call, stack, or call-stack are.
because it might crash.
Why does that change the type? We can construct bottoms like `let x in x` that crash the program without changing the type.
So HasCallStack => [Integer] is a [Integer]
What makes this even more obnoxious is that when we finally do introduce typeclasses and constraints, we talk about constraining a _type variable_ and now you've baked this magic in they cannot possibly be explained at all in the book.
that might crash and produce a stack-trace
First bit they might pick up from context, they don't know what a stack trace is. Bonus round: when you explain things "from first principles", you can't duck the fact that it's actually a call graph when explaining a "stack" trace or call stack. Now you have to explain why/how it gets flattened from one representation into the other.
Oliver had it when he said,
"What's a call stack?"
They don't know what a stack, a call, or the combination thereof is. We had planned to address these issues in the (much later) chapters that cover profiling and errors. Because that's when they're relevant. This hasn't been relevant the entire span of the book. It _never_ mattered that you didn't get a stack trace from bottoms. In practice, does it suck? Sure! But
not practitioners yet! I am (I use Haskell for my 9-5 and have done for a year and a half) and it still hasn't mattered to me. The only time I've really wanted a stack trace is when this mechanism would not have been available to me to begin with.
Gamari / amindfv
I don't have a copy of GHC 8 atm to test this with: is an expression
On Sat, Feb 13, 2016 at 8:52 PM, Christopher Allen
wrote: they they're like this now illegal?
x :: Int x = undefined
This is still valid. The change in GHC 8.0 is merely that GHC will infer a CallStack constraint instead of solving it in-place if asked to infer a type for a let binding whose RHS demands a callstack.
We have readers use the REPL _a lot_. Not only to load code but also free-standing expressions in the REPL when experimenting and learning. Type assignment in the REPL is noisy and we have to write around some pretty gnarly width limitations (40-60 cols). This breaks the examples where we're combining bottom and type inference to explore how terms and types interact.
I am less disturbed by `HasCallStack =>` than I was by the inferred type of ($).
I know designing around pedagogical limitations like this is tedious but imagine doing it for 900-1,200 pages (formatting varies) of tutorial and exercises, then getting unpleasant surprises right as the book is about to be done.
Sorry about the messy thread all.
[1]: http://haskellformac.com/
On Sat, Feb 13, 2016 at 1:48 PM, Bryan Richter wrote:
On Sat, Feb 13, 2016 at 09:18:07AM -0800, Eric Seidel wrote:
Here's what the GHCi session should look like.
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for
help
Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
What use case is satisfied by providing this information? How does it benefit the Haskell programmer? How do I use it?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com

There's another problem I discovered with HasCallStack. The implicit
parameter constraint breaks sharing behavior for examples that use bottom.
Observe:
$ ghci
GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/callen/.ghci
Prelude> let myList = [1, 2, id 1] :: [Integer]
Prelude> let myList' = myList ++ undefined
Prelude> :sprint myList'
myList' = _
Prelude> head myList'
1
Prelude> :sprint myList'
myList' = _
Prelude> :t myList'
myList' :: (?callStack::GHC.Stack.Types.CallStack) => [Integer]
Prelude> take 2 myList'
[1,2]
Prelude> :sprint myList'
myList' = _
$ stack ghci
Run from outside a project, using implicit global project config
Using resolver: lts-5.1 from implicit global project's config file:
/home/callen/.stack/global-project/stack.yaml
Error parsing targets: The specified targets matched no packages.
Perhaps you need to run 'stack init'?
Warning: build failed, but optimistically launching GHCi anyway
Configuring GHCi with the following packages:
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
Ok, modules loaded: none.
Prelude> let myList = [1, 2, id 1] :: [Integer]
Prelude> let myList' = myList ++ undefined
Prelude> :sprint myList'
myList' = _
Prelude> head myList'
1
Prelude> :sprint myList'
myList' = 1 : _
Prelude> take 2 myList'
[1,2]
Prelude> :sprint myList'
myList' = 1 : 2 : _
Now I have to re-examine everywhere we've used bottoms and :sprint together
in the book, which includes the chapters on lists, folds, and
non-strictness. And it isn't just about our book, what about all the other
learning resources and tutorials? :sprint was hard enough for new people to
understand to begin with.
It is very disheartening that people do not take this more seriously.
On Sat, Feb 13, 2016 at 3:33 PM, Christopher Allen
Holes and bottoms are wildly different. Bottoms are considerably more useful which I think you'd find if you ran down a list of examples and tried both in each circumstance. This would force even more rewriting than present circumstances.
'undefined' is nasty and has to be used with care
Ya, we tell them that. We also tell them that programs intended to be executed outside of a learning/development environment should be total (we explain totality and partiality).
On Sat, Feb 13, 2016 at 3:08 PM, Matthew Pickering < matthewtpickering@gmail.com> wrote:
Maybe it would be better to introduce _ rather than using undefined for holes in programs. This sidesteps this issue, provides useful information to guide the implementation and causes an error when code is compiled so programs aren't unexpectedly partial.
It is perhaps not idiomatic to use undefined, even in development these days. It is much easier (imo) to use holes and -fdefer-type-errors.
'undefined' is nasty and has to be used with care; CallStacks exist as a bit of a safety net. I've not read your book but I'm not convinced it should be emphasised so much in the first chapters of an elementary Haskell textbook.
Replying to a few here.
Gigante:
Just a question: how do you manage the type of simple arithmetic expressions like 1 + 1? I mean, the type contains a constraint there. Prelude> :t 1 + 1 1 + 1 :: Num a => a
Earlier versions of the book intentionally juked this or concreted the type of numbers to Integer, but HaskellForMac defenestrated that with the always-on type showing so now we've had an explanation along the lines you suggest for a few months now. We know how to adapt - we've tested the book extensively. What we need is the implementation not to expose irrelevant magic/noise in ways that could leak into the first chapter with Haskell code in it.
Seidel:
If your readers are using :t they must already know about simple types like Integer, [], and, ->, so the new things are HasCallStack and =>.
You'd bloody think as we're careful when we introduce :t, but we get tickets from people using HaskellForMac[1] that get confused because they are shown the types of expressions too early. Now we're careful in how we introduce _any_ expressions.
Fisking your attempt:
=> is just like -> except
They don't know what either of those things are or what they mean in the second chapter because this is the _first_ chapter with any Haskell code. They're just beginning to see how Haskell code might be kinda like the lambdas in the lambda calculus chapter.
the compiler fills in the argument by
We do explain what a compiler and interpreter are, but they won't know what it means for it to fill in an argument. They don't know why it needs to fill in an argument. Where did the argument come from?
HasCallStack tells the compiler
How? Why? Why do they need to care? What's a HasCallStack? Keep in mind
don't know types, typeclasses, or anything else.
that the expression needs a call-stack
Still don't know what a call, stack, or call-stack are.
because it might crash.
Why does that change the type? We can construct bottoms like `let x in x` that crash the program without changing the type.
So HasCallStack => [Integer] is a [Integer]
What makes this even more obnoxious is that when we finally do introduce typeclasses and constraints, we talk about constraining a _type variable_ and now you've baked this magic in they cannot possibly be explained at all in the book.
that might crash and produce a stack-trace
First bit they might pick up from context, they don't know what a stack trace is. Bonus round: when you explain things "from first principles", you can't duck the fact that it's actually a call graph when explaining a "stack" trace or call stack. Now you have to explain why/how it gets flattened from one representation into the other.
Oliver had it when he said,
"What's a call stack?"
They don't know what a stack, a call, or the combination thereof is. We had planned to address these issues in the (much later) chapters that cover profiling and errors. Because that's when they're relevant. This hasn't been relevant the entire span of the book. It _never_ mattered that you didn't get a stack trace from bottoms. In practice, does it suck? Sure! But
not practitioners yet! I am (I use Haskell for my 9-5 and have done for a year and a half) and it still hasn't mattered to me. The only time I've really wanted a stack trace is when this mechanism would not have been available to me to begin with.
Gamari / amindfv
I don't have a copy of GHC 8 atm to test this with: is an expression
On Sat, Feb 13, 2016 at 8:52 PM, Christopher Allen
wrote: they they're like this now illegal?
x :: Int x = undefined
This is still valid. The change in GHC 8.0 is merely that GHC will infer a CallStack constraint instead of solving it in-place if asked to infer a type for a let binding whose RHS demands a callstack.
We have readers use the REPL _a lot_. Not only to load code but also free-standing expressions in the REPL when experimenting and learning. Type assignment in the REPL is noisy and we have to write around some pretty gnarly width limitations (40-60 cols). This breaks the examples where we're combining bottom and type inference to explore how terms and types interact.
I am less disturbed by `HasCallStack =>` than I was by the inferred type of ($).
I know designing around pedagogical limitations like this is tedious but imagine doing it for 900-1,200 pages (formatting varies) of tutorial and exercises, then getting unpleasant surprises right as the book is about to be done.
Sorry about the messy thread all.
[1]: http://haskellformac.com/
On Sat, Feb 13, 2016 at 1:48 PM, Bryan Richter wrote:
On Sat, Feb 13, 2016 at 09:18:07AM -0800, Eric Seidel wrote:
Here's what the GHCi session should look like.
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for
help
Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
What use case is satisfied by providing this information? How does it benefit the Haskell programmer? How do I use it?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com
-- Chris Allen Currently working on http://haskellbook.com

Notice that in your example unless "myList" is given an explicit type signature then sharing is also affected. See also this ticket: https://ghc.haskell.org/trac/ghc/ticket/11383
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.
The roadmap[1] has a comprehensive list of features which have made it into HEAD. There is also quite a long wiki page[2] for this feature. Is that sufficient? I don't think it's feasible to maintainer a list of parties interested in GHC and notify them whenever anything changes. Matt [1]: https://ghc.haskell.org/trac/ghc/wiki/Status/GHC-8.0.1 [2]: https://ghc.haskell.org/trac/ghc/wiki/ExplicitCallStack/ImplicitLocations
On Sat, Feb 13, 2016 at 3:33 PM, Christopher Allen
wrote: Holes and bottoms are wildly different. Bottoms are considerably more useful which I think you'd find if you ran down a list of examples and tried both in each circumstance. This would force even more rewriting than present circumstances.
'undefined' is nasty and has to be used with care
Ya, we tell them that. We also tell them that programs intended to be executed outside of a learning/development environment should be total (we explain totality and partiality).
On Sat, Feb 13, 2016 at 3:08 PM, Matthew Pickering
wrote: Maybe it would be better to introduce _ rather than using undefined for holes in programs. This sidesteps this issue, provides useful information to guide the implementation and causes an error when code is compiled so programs aren't unexpectedly partial.
It is perhaps not idiomatic to use undefined, even in development these days. It is much easier (imo) to use holes and -fdefer-type-errors.
'undefined' is nasty and has to be used with care; CallStacks exist as a bit of a safety net. I've not read your book but I'm not convinced it should be emphasised so much in the first chapters of an elementary Haskell textbook.
On Sat, Feb 13, 2016 at 8:52 PM, Christopher Allen
wrote: Replying to a few here.
Gigante:
Just a question: how do you manage the type of simple arithmetic expressions like 1 + 1? I mean, the type contains a constraint there. Prelude> :t 1 + 1 1 + 1 :: Num a => a
Earlier versions of the book intentionally juked this or concreted the type of numbers to Integer, but HaskellForMac defenestrated that with the always-on type showing so now we've had an explanation along the lines you suggest for a few months now. We know how to adapt - we've tested the book extensively. What we need is the implementation not to expose irrelevant magic/noise in ways that could leak into the first chapter with Haskell code in it.
Seidel:
If your readers are using :t they must already know about simple types like Integer, [], and, ->, so the new things are HasCallStack and =>.
You'd bloody think as we're careful when we introduce :t, but we get tickets from people using HaskellForMac[1] that get confused because they are shown the types of expressions too early. Now we're careful in how we introduce _any_ expressions.
Fisking your attempt:
=> is just like -> except
They don't know what either of those things are or what they mean in the second chapter because this is the _first_ chapter with any Haskell code. They're just beginning to see how Haskell code might be kinda like the lambdas in the lambda calculus chapter.
the compiler fills in the argument by
We do explain what a compiler and interpreter are, but they won't know what it means for it to fill in an argument. They don't know why it needs to fill in an argument. Where did the argument come from?
HasCallStack tells the compiler
How? Why? Why do they need to care? What's a HasCallStack? Keep in mind they don't know types, typeclasses, or anything else.
that the expression needs a call-stack
Still don't know what a call, stack, or call-stack are.
because it might crash.
Why does that change the type? We can construct bottoms like `let x in x` that crash the program without changing the type.
So HasCallStack => [Integer] is a [Integer]
What makes this even more obnoxious is that when we finally do introduce typeclasses and constraints, we talk about constraining a _type variable_ and now you've baked this magic in they cannot possibly be explained at all in the book.
that might crash and produce a stack-trace
First bit they might pick up from context, they don't know what a stack trace is. Bonus round: when you explain things "from first principles", you can't duck the fact that it's actually a call graph when explaining a "stack" trace or call stack. Now you have to explain why/how it gets flattened from one representation into the other.
Oliver had it when he said,
"What's a call stack?"
They don't know what a stack, a call, or the combination thereof is. We had planned to address these issues in the (much later) chapters that cover profiling and errors. Because that's when they're relevant. This hasn't been relevant the entire span of the book. It _never_ mattered that you didn't get a stack trace from bottoms. In practice, does it suck? Sure! But they're not practitioners yet! I am (I use Haskell for my 9-5 and have done for a year and a half) and it still hasn't mattered to me. The only time I've really wanted a stack trace is when this mechanism would not have been available to me to begin with.
Gamari / amindfv
I don't have a copy of GHC 8 atm to test this with: is an expression like this now illegal?
x :: Int x = undefined
This is still valid. The change in GHC 8.0 is merely that GHC will infer a CallStack constraint instead of solving it in-place if asked to infer a type for a let binding whose RHS demands a callstack.
We have readers use the REPL _a lot_. Not only to load code but also free-standing expressions in the REPL when experimenting and learning. Type assignment in the REPL is noisy and we have to write around some pretty gnarly width limitations (40-60 cols). This breaks the examples where we're combining bottom and type inference to explore how terms and types interact.
I am less disturbed by `HasCallStack =>` than I was by the inferred type of ($).
I know designing around pedagogical limitations like this is tedious but imagine doing it for 900-1,200 pages (formatting varies) of tutorial and exercises, then getting unpleasant surprises right as the book is about to be done.
Sorry about the messy thread all.
[1]: http://haskellformac.com/
On Sat, Feb 13, 2016 at 1:48 PM, Bryan Richter wrote:
On Sat, Feb 13, 2016 at 09:18:07AM -0800, Eric Seidel wrote:
Here's what the GHCi session should look like.
> $ ghci > GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/ :? for > help > Loaded GHCi configuration from /home/callen/.ghci > Prelude> let myList = [1..5 :: Integer] > Prelude> let myList' = myList ++ undefined > Prelude> :t myList' > myList' :: HasCallStack => [Integer]
What use case is satisfied by providing this information? How does it benefit the Haskell programmer? How do I use it?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com
-- Chris Allen Currently working on http://haskellbook.com

On Sat, Feb 13, 2016, at 15:32, Christopher Allen wrote:
There's another problem I discovered with HasCallStack. The implicit parameter constraint breaks sharing behavior for examples that use bottom.
This is a necessary consequence of the implementation of callstack-aware functions as overloaded functions. It's really no different from using a type-class, and is in my opinion the correct behavior. It seems what you really want is a way to prevent GHC from inferring the HasCallStack constraint in the first place. That's doable with an explicit type signature (or even a combinator to wrap the expression), but this isn't a great solution for your book. What I'd suggest instead is to define your own undefined in a Prelude-replacement (or simplification if you will). Something like undefined :: a undefined = withFrozenCallStack emptyCallStack Prelude.undefined should work to remove all traces of CallStacks (including when it blows up). error can be similarly wrapped to avoid having to deal with CallStacks, and $ and the FTP-related functions can be specialized to less-polymorphic versions that are easier to explain to beginners (at least until they're ready to be exposed to the real versions). I'm sorry that this change has caused you trouble.

What I'd suggest instead is to define your own undefined in a Prelude-replacement (or simplification if you will).
No. Part of the reason for the book is so that people can learn in the
environment that they'll use and be equipped to apply what they've learned
with minimal surprises. This solution is worse than the others suggested so
far. And _again_, it's not just about our book it's about learning
resources more generally and what that experience is like for new people.
Rust doesn't need to have a beginner's Prelude. Idris doesn't either. In
fact, most languages don't and the only one that has pulled it off
convincingly is Racket which had less cause to do so than GHC does at this
juncture.
On Sat, Feb 13, 2016 at 6:02 PM, Eric Seidel
On Sat, Feb 13, 2016, at 15:32, Christopher Allen wrote:
There's another problem I discovered with HasCallStack. The implicit parameter constraint breaks sharing behavior for examples that use bottom.
This is a necessary consequence of the implementation of callstack-aware functions as overloaded functions. It's really no different from using a type-class, and is in my opinion the correct behavior.
It seems what you really want is a way to prevent GHC from inferring the HasCallStack constraint in the first place. That's doable with an explicit type signature (or even a combinator to wrap the expression), but this isn't a great solution for your book.
What I'd suggest instead is to define your own undefined in a Prelude-replacement (or simplification if you will). Something like
undefined :: a undefined = withFrozenCallStack emptyCallStack Prelude.undefined
should work to remove all traces of CallStacks (including when it blows up). error can be similarly wrapped to avoid having to deal with CallStacks, and $ and the FTP-related functions can be specialized to less-polymorphic versions that are easier to explain to beginners (at least until they're ready to be exposed to the real versions).
I'm sorry that this change has caused you trouble. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com

I've put together a patch to prevent GHC from inferring CallStacks for *top-level* expressions. Given that we've hidden the implicit parameter behind a type synonym (and may remove it entirely in the future), I'm less concerned about preserving the expected behavior for implicit parameters. I believe this should address most of your concerns wrt ghci interactions. ghci> let myList = [1, 2, 3 :: Integer] myList :: [Integer] ghci> let myList' = myList ++ undefined myList' :: [Integer] ghci> :t myList myList :: [Integer] ghci> :t myList' myList' :: [Integer] ghci> :sprint myList' myList' = _ ghci> head myList' 1 it :: Integer ghci> :sprint myList' myList' = 1 : _ Note that undefined still takes a CallStack, and thus has a more involved type. ghci> :t undefined undefined :: forall (v :: GHC.Types.Levity) (a :: TYPE v). GHC.Stack.Types.HasCallStack => a But uses of undefined will no longer infect the top-level context with CallStacks, you'll have to request them explicitly. (We need the inference for local binders, so HaskellForMac and ghc-mod could still show CallStacks in tooltips). The patch is awaiting review at https://phabricator.haskell.org/D1912, you're more than welcome to comment. Eric On Sat, Feb 13, 2016, at 16:49, Christopher Allen wrote:
What I'd suggest instead is to define your own undefined in a Prelude-replacement (or simplification if you will).
No. Part of the reason for the book is so that people can learn in the environment that they'll use and be equipped to apply what they've learned with minimal surprises. This solution is worse than the others suggested so far. And _again_, it's not just about our book it's about learning resources more generally and what that experience is like for new people.
Rust doesn't need to have a beginner's Prelude. Idris doesn't either. In fact, most languages don't and the only one that has pulled it off convincingly is Racket which had less cause to do so than GHC does at this juncture.
On Sat, Feb 13, 2016 at 6:02 PM, Eric Seidel
wrote: On Sat, Feb 13, 2016, at 15:32, Christopher Allen wrote:
There's another problem I discovered with HasCallStack. The implicit parameter constraint breaks sharing behavior for examples that use bottom.
This is a necessary consequence of the implementation of callstack-aware functions as overloaded functions. It's really no different from using a type-class, and is in my opinion the correct behavior.
It seems what you really want is a way to prevent GHC from inferring the HasCallStack constraint in the first place. That's doable with an explicit type signature (or even a combinator to wrap the expression), but this isn't a great solution for your book.
What I'd suggest instead is to define your own undefined in a Prelude-replacement (or simplification if you will). Something like
undefined :: a undefined = withFrozenCallStack emptyCallStack Prelude.undefined
should work to remove all traces of CallStacks (including when it blows up). error can be similarly wrapped to avoid having to deal with CallStacks, and $ and the FTP-related functions can be specialized to less-polymorphic versions that are easier to explain to beginners (at least until they're ready to be exposed to the real versions).
I'm sorry that this change has caused you trouble. _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Chris Allen Currently working on http://haskellbook.com

Who isn’t taking it seriously? See https://ghc.haskell.org/trac/ghc/ticket/11573https://ghc.haskell.org/trac/ghc/ticket/11573#comment:3
Simon
From: Haskell-Cafe [mailto:haskell-cafe-bounces@haskell.org] On Behalf Of Christopher Allen
Sent: 13 February 2016 23:33
To: Matthew Pickering
'undefined' is nasty and has to be used with care
Ya, we tell them that. We also tell them that programs intended to be executed outside of a learning/development environment should be total (we explain totality and partiality).
On Sat, Feb 13, 2016 at 3:08 PM, Matthew Pickering
Replying to a few here.
Gigante:
Just a question: how do you manage the type of simple arithmetic expressions like 1 + 1? I mean, the type contains a constraint there. Prelude> :t 1 + 1 1 + 1 :: Num a => a
Earlier versions of the book intentionally juked this or concreted the type of numbers to Integer, but HaskellForMac defenestrated that with the always-on type showing so now we've had an explanation along the lines you suggest for a few months now. We know how to adapt - we've tested the book extensively. What we need is the implementation not to expose irrelevant magic/noise in ways that could leak into the first chapter with Haskell code in it.
Seidel:
If your readers are using :t they must already know about simple types like Integer, [], and, ->, so the new things are HasCallStack and =>.
You'd bloody think as we're careful when we introduce :t, but we get tickets from people using HaskellForMac[1] that get confused because they are shown the types of expressions too early. Now we're careful in how we introduce _any_ expressions.
Fisking your attempt:
=> is just like -> except
They don't know what either of those things are or what they mean in the second chapter because this is the _first_ chapter with any Haskell code. They're just beginning to see how Haskell code might be kinda like the lambdas in the lambda calculus chapter.
the compiler fills in the argument by
We do explain what a compiler and interpreter are, but they won't know what it means for it to fill in an argument. They don't know why it needs to fill in an argument. Where did the argument come from?
HasCallStack tells the compiler
How? Why? Why do they need to care? What's a HasCallStack? Keep in mind they don't know types, typeclasses, or anything else.
that the expression needs a call-stack
Still don't know what a call, stack, or call-stack are.
because it might crash.
Why does that change the type? We can construct bottoms like `let x in x` that crash the program without changing the type.
So HasCallStack => [Integer] is a [Integer]
What makes this even more obnoxious is that when we finally do introduce typeclasses and constraints, we talk about constraining a _type variable_ and now you've baked this magic in they cannot possibly be explained at all in the book.
that might crash and produce a stack-trace
First bit they might pick up from context, they don't know what a stack trace is. Bonus round: when you explain things "from first principles", you can't duck the fact that it's actually a call graph when explaining a "stack" trace or call stack. Now you have to explain why/how it gets flattened from one representation into the other.
Oliver had it when he said,
"What's a call stack?"
They don't know what a stack, a call, or the combination thereof is. We had planned to address these issues in the (much later) chapters that cover profiling and errors. Because that's when they're relevant. This hasn't been relevant the entire span of the book. It _never_ mattered that you didn't get a stack trace from bottoms. In practice, does it suck? Sure! But they're not practitioners yet! I am (I use Haskell for my 9-5 and have done for a year and a half) and it still hasn't mattered to me. The only time I've really wanted a stack trace is when this mechanism would not have been available to me to begin with.
Gamari / amindfv
I don't have a copy of GHC 8 atm to test this with: is an expression like this now illegal?
x :: Int x = undefined
This is still valid. The change in GHC 8.0 is merely that GHC will infer a CallStack constraint instead of solving it in-place if asked to infer a type for a let binding whose RHS demands a callstack.
We have readers use the REPL _a lot_. Not only to load code but also free-standing expressions in the REPL when experimenting and learning. Type assignment in the REPL is noisy and we have to write around some pretty gnarly width limitations (40-60 cols). This breaks the examples where we're combining bottom and type inference to explore how terms and types interact.
I am less disturbed by `HasCallStack =>` than I was by the inferred type of ($).
I know designing around pedagogical limitations like this is tedious but imagine doing it for 900-1,200 pages (formatting varies) of tutorial and exercises, then getting unpleasant surprises right as the book is about to be done.
Sorry about the messy thread all.
[1]: http://haskellformac.com/https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fhaskellformac.com%2f&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c88ed552870fa4edd065e08d334ce0121%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=bIetRAnTyz1Ueg8GpQA56L5TouGYLB8Vkiz%2boaVpLDI%3d
On Sat, Feb 13, 2016 at 1:48 PM, Bryan Richter mailto:b@chreekat.net> wrote:
On Sat, Feb 13, 2016 at 09:18:07AM -0800, Eric Seidel wrote:
Here's what the GHCi session should look like.
$ ghci GHCi, version 8.0.0.20160204: http://www.haskell.org/ghc/https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fwww.haskell.org%2fghc%2f&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c88ed552870fa4edd065e08d334ce0121%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=0P%2f9ZjJzpKYrfiMu8gwypRghsPlSq6QSjipOZWzi2HQ%3d :? for help Loaded GHCi configuration from /home/callen/.ghci Prelude> let myList = [1..5 :: Integer] Prelude> let myList' = myList ++ undefined Prelude> :t myList' myList' :: HasCallStack => [Integer]
What use case is satisfied by providing this information? How does it benefit the Haskell programmer? How do I use it?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.orgmailto:Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafehttps://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haskell.org%2fcgi-bin%2fmailman%2flistinfo%2fhaskell-cafe&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c88ed552870fa4edd065e08d334ce0121%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=R%2btoKh2iN3iHX%2fVljSJ6eIdVUcJy0SRUqprLQGBHVr4%3d
-- Chris Allen Currently working on http://haskellbook.comhttps://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fhaskellbook.com&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c88ed552870fa4edd065e08d334ce0121%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=UtHWa8XKNAIVAtDzB2p%2bBh2Ps6isQuIHzeePLa8cSgA%3d
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.orgmailto:Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafehttps://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.haskell.org%2fcgi-bin%2fmailman%2flistinfo%2fhaskell-cafe&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c88ed552870fa4edd065e08d334ce0121%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=R%2btoKh2iN3iHX%2fVljSJ6eIdVUcJy0SRUqprLQGBHVr4%3d
-- Chris Allen Currently working on http://haskellbook.comhttps://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fhaskellbook.com&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c88ed552870fa4edd065e08d334ce0121%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=UtHWa8XKNAIVAtDzB2p%2bBh2Ps6isQuIHzeePLa8cSgA%3d -- Chris Allen Currently working on http://haskellbook.comhttps://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fhaskellbook.com&data=01%7c01%7csimonpj%40064d.mgd.microsoft.com%7c88ed552870fa4edd065e08d334ce0121%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=UtHWa8XKNAIVAtDzB2p%2bBh2Ps6isQuIHzeePLa8cSgA%3d

On Sat, Feb 13, 2016, at 01:04, Oliver Charles wrote:
Just a clarification - the presence of that parameter does not say "I use call stack" but rather "I need *a* call stack". This subtle difference means that you do need to know about this due to how stacks work in GHC. If you use error and then don't also add that constraint yourself to your function, youll only see part of the stack. Hence it more than just UX noise - I have a decision to make, and building a call stack gas a cost.
Also, is this RC2? I thought this was now changed to use constraint kinds and type alias the implicit parameter behind a nicer API.
Yes, RC2 still infers implicit parameter constraints as opposed to HasCallStack constraints. This is a bug, and it should be a simple fix. Eric
participants (11)
-
amindfv@gmail.com
-
Ben Gamari
-
Bryan Richter
-
Christopher Allen
-
Eric Seidel
-
Matthew Pickering
-
Nicola Gigante
-
Oliver Charles
-
Rustom Mody
-
Simon Peyton Jones
-
Will Yager