Skip to content

Two problems with Language.Haskell.TH.Ppr.pprint

Summary

Language.Haskell.TH.Ppr.pprint, when applied to a Language.Haskell.TH.Lit or Language.Haskell.TH.Exp value, can produce output that doesn't parse to the original literal or expression.

Steps to reproduce

$ ghci
> :set -XNegativeLiterals -XTemplateHaskell

RationalL

> Language.Haskell.TH.runQ [| 1.5 |] >>= print . Language.Haskell.TH.Ppr.pprint
"3 / 2"

Note that 3 / 2 is not a literal value, even though it evaluates to the same ground value as the original literal 1.5.

ArithSeqE

> Language.Haskell.TH.runQ [| [-4 .. -1] |] >>= print . Language.Haskell.TH.Ppr.pprint
"[-4..-1]"
> [-4..-1]

<interactive>:5:4: error:
    Variable not in scope: (..-) :: t0 -> t1 -> a

Expected behavior

> :set -XNegativeLiterals -XTemplateHaskell

RationalL

> Language.Haskell.TH.runQ [| 1.5 |] >>= print . Language.Haskell.TH.Ppr.pprint
"1.5"

Now that's a literal. In anticipation of a potential objection, note that it's syntactically impossible to produce a literal value in Haskell with an infinite number of decimal digits. In other words, a TH value like RationalL (1 / 3) does not correspond to any Haskell literal.

ArithSeqE

> Language.Haskell.TH.runQ [| [-4 .. -1] |] >>= print . Language.Haskell.TH.Ppr.pprint
"[-4 .. -1]"
> [-4 .. -1]
[-4,-3,-2,-1]

The inserted spaces would make the pprint output valid with NegativeLiterals.

Environment

  • GHC version used: 9.0.1

Optional:

  • Operating System: Ubuntu Linux
  • System Architecture: amd64
Edited by Mario
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information