Desugaring matches with already-desugared RHSs?

Alexis King lexi.lambda at gmail.com
Sun Apr 26 01:40:00 UTC 2020


Hi all,

I’m currently in the process of rewriting most of the arrow desugaring
code. One of the most awkward parts of the current implementation is
the way case commands are desugared. Given a case command like

    case e1 of
      A a b   -> cmd1
      B c     -> cmd2
      C d e f -> cmd3

the desugarer actually replaces each command on the RHS with an
Either-wrapped tuple to get something like this:

    arr (\env -> case e1 of
          A a b   -> Left (Left (a, b))
          B c     -> Left (Right c)
          C d e f -> Right (d, e, f))
    >>> ((cmd1 ||| cmd2) ||| cmd3)

This means the RHSs of the case expression are really already
desugared, and ideally they would be CoreExprs, but matchWrapper
expects the RHSs to be HsExprs. The current implementation
accommodates this restriction by building fake HsExprs with no
location information, but this means the logic for building the tuples
in the RHSs has to be duplicated (since other places do want
CoreExprs).

I was thinking it would be nice to avoid this hack, but I’m not sure
what the best way to do it is. One way would be to create a variant of
matchWrapper with a type like

    matchWrapper'
      :: HsMatchContext GhcRn
      -> Maybe (LHsExpr GhcTc)
      -> MatchGroup GhcTc rhs
      -> (rhs -> DsM CoreExpr)  -- how to desugar the RHSs
      -> DsM ([Id], CoreExpr)

and update dsGRHSs to accept an extra argument as well. Then the arrow
desugaring code could just pass `return` to matchWrapper' so it
wouldn’t touch its RHSs. But I’m not sure if this approach makes sense
— nothing else in the desugarer seems to work this way. Is there a
better approach I’m not seeing?

Thanks,
Alexis


More information about the ghc-devs mailing list