Simon Peyton-Jones wrote:
| In GHC 5.04.1, derived instances of Show mishandle precedence: | | Prelude> putStrLn (showsPrec 10 (Just 0) "") | Just 0 | | The result should be: (Just 0)
I think it's a bug in the Report, not in GHC, actually. The Report says (Section D.4)
"The function 'showsPrec d x r' accepts a precedence level 'd' (a number from 0 to 10), a value 'x', and a string 'r'. .... "The representation will be enclosed in parentheses if the precedence of the top-level constructor operator in 'x' is less than 'd'. Thus, if 'd' is 0 then the result is never surrounded in parentheses; if 'd' is 10 it is always surrounded in parentheses, unless it is an atomic expression."
But in fact, the precedence of function application is 10, as the syntax makes clear. Indeed, the example code at the end of Appendix D shows a call to showsPrec with an argument of 11 (it's written "app_prec + 1"), for precisely this reason.
So, I think that I have to make these changes to the Report:
(A) The last sentence should say "..; if 'd' is 11 it is always surrounded in parentheses, unless it is an atomic expression (recall, function application has precedence 10)".
(B) The earlier parenthesis should say "(a number from 0 to 11)".
Does anyone disagree?
I agree. I note that GHC recently (5.04.1?) changed to match the changes you propose above, and Hugs (as of Dec. 2001 version) still matches the current report. I reread Appendix D in the revised report (<http://research.microsoft.com/Users/simonpj/haskell98-revised/haskell98-report-html/derived.html>) and have some additional comments. (1) In the first section, in: instance (cx, cx') => Ci (T u1 ... uk) where { d } the use of "(cs, cs')" is a bit loose (that is, suggestive rather than precise syntax). One can't (according to the report, though GHC seems to allow it) have nested parentheses in a context, which would occur if cx included parentheses. (2) In section D.1, in: For example, False < _|_ is _|_, even though False is the first constructor of the Bool type. change the operator from "<" to "<=". There is no reason to expect (False < _|_) to be True. (3) Section D.4 gives the expected rule: head (readsPrec d (showsPrec d x "")) == (x,"") Why should this not be: readsPrec d (showsPrec d x "") == [(x,"")] (4) I don't understand this paragraph in section D.4: readsPrec will parse any valid representation of the standard types apart from lists, for which only the bracketed form [...] is accepted. See Appendix A for full details. The statement seems to say that ((readsPrec 5 (show "abc"))::[([Char],String)]) is invalid, but that can't be what it means to say. (5) The next paragraph of section D.4 says: Spaces and parentheses are only added where needed, ignoring associativity. The phrase "only where needed" suggests that (show (1 :$ 2 :$ NT)) should produce the string "1:$(2:$NT)" (no spaces) rather than the string "1 :$ (2 :$ NT)", as claimed later in the section (and borne out by GHC). It needs to be stated that an infix operator is preceded and followed by a space. (6) In the bullet that begins "The derived Read instance allows", change "parenthese" to "parentheses". -- Dean