Skip to content

Text.ParserCombinators.ReadP badly needs eta-expansion

Looking through some generated Core for Text.Read.Lex (for example lexHexOct) revealed that ReadP is almost never eta-expanded:

$wlexHexOct_r5XJ                                                                                                                                                                                  :: forall {b}.
     (Lexeme -> Text.ParserCombinators.ReadP.P b)
     -> Char -> Text.ParserCombinators.ReadP.P b
[GblId, Arity=2, Str=<U><SP(SU)>, Unf=OtherCon []]
$wlexHexOct_r5XJ
  = \ (@b_s4mE)
      (w_s4mF :: Lexeme -> Text.ParserCombinators.ReadP.P b_s4mE)
      (eta_B0 :: Char) ->
      case eta_B0 of { C# y_a2vO ->
      case y_a2vO of {
        __DEFAULT -> Text.ParserCombinators.ReadP.Fail @b_s4mE;
        '0'# ->
          let {
            lvl127_s4Vf :: Digits -> Text.ParserCombinators.ReadP.P b_s4mE
            [LclId, Arity=1, Str=<U>, Unf=OtherCon []]
            lvl127_s4Vf
              = \ (a1_Xk :: Digits) ->
                  w_s4mF
                    (Text.Read.Lex.Number
                       (Text.Read.Lex.MkNumber lvl5_r5X1 a1_Xk)) } in
          let {
            lvl128_s4Vg :: String -> Text.ParserCombinators.ReadP.P b_s4mE
            [LclId, Unf=OtherCon []]
            lvl128_s4Vg = $wlexDigits_r5XI lvl5_r5X1 @b_s4mE lvl127_s4Vf } in
          let {
            lvl129_s4NC :: Text.ParserCombinators.ReadP.P b_s4mE
            [LclId, Unf=OtherCon []]
            lvl129_s4NC
              = Text.ParserCombinators.ReadP.Look @b_s4mE lvl128_s4Vg } in
          let {
            lvl130_s4Vh :: Digits -> Text.ParserCombinators.ReadP.P b_s4mE
            [LclId, Arity=1, Str=<U>, Unf=OtherCon []]
            lvl130_s4Vh
              = \ (a1_Xk :: Digits) ->
                  w_s4mF
                    (Text.Read.Lex.Number
                       (Text.Read.Lex.MkNumber lvl4_r5X0 a1_Xk)) } in
          let {
            lvl131_s4Vi :: String -> Text.ParserCombinators.ReadP.P b_s4mE
            [LclId, Unf=OtherCon []]
            lvl131_s4Vi = $wlexDigits_r5XI lvl4_r5X0 @b_s4mE lvl130_s4Vh } in
          let {
            lvl132_s4Nz :: Text.ParserCombinators.ReadP.P b_s4mE
            [LclId, Unf=OtherCon []]
            lvl132_s4Nz
              = Text.ParserCombinators.ReadP.Look @b_s4mE lvl131_s4Vi } in
          Text.ParserCombinators.ReadP.Get
            @b_s4mE
            (\ (eta1_Xj :: Char) ->
               case eta1_Xj of { C# ds_d29y ->
               case ds_d29y of {
                 __DEFAULT -> Text.ParserCombinators.ReadP.Fail @b_s4mE;
                 'O'# -> lvl132_s4Nz;
                 'X'# -> lvl129_s4NC;
                 'o'# -> lvl132_s4Nz;
                 'x'# -> lvl129_s4NC
               }
               })
      }
      }

This is all due to the CPS encoding. lexDigits there is properly eta-expanded, but for some reason usage analysis can't figure out that the passed continuation is always called with one argument. Chaos! I imagine this is also true for any other module employing ReadP.

This could be fixed by employing the one-shot monad trick.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information