[GHC] #7828: RebindableSyntax and Arrow

GHC ghc-devs at haskell.org
Tue Jun 17 17:24:29 UTC 2014


#7828: RebindableSyntax and Arrow
----------------------------------------------+----------------------------
        Reporter:  AlessandroVermeulen        |            Owner:
            Type:  bug                        |  jstolarek
        Priority:  normal                     |           Status:  new
       Component:  Compiler (Type checker)    |        Milestone:  7.10.1
      Resolution:                             |          Version:  7.6.2
Operating System:  Unknown/Multiple           |         Keywords:
 Type of failure:  GHC rejects valid program  |     Architecture:
       Test Case:                             |  Unknown/Multiple
        Blocking:                             |       Difficulty:  Unknown
                                              |       Blocked By:
                                              |  Related Tickets:  #1537,
                                              |  #3613
----------------------------------------------+----------------------------

Comment (by ross):

 Replying to [comment:30 jstolarek]:
 > A few more questions to make sure that I understand:
 >
 > 1. If your solution was implemented then `bind`, `bind_` and
 `ifThenElseA` would be rebindable and `arr` & friends would not?

 Yes.

 > 2. `bind`, `bind_` and `ifThenElseA` currently don't exist in the
 libraries. Implementing yor proposal would require adding their
 definitions to Control.Arrow. Desugared arrow notation would call these
 default definitions, unless `RebindableSyntax` is enabled, in which case
 we use the definitions of `bind` etc. that are currently in scope.
 Correct?

 It would probably be helpful to add them, but it wouldn't be necessary,
 just as the libraries don't currently have a definition of `ifThenElse`.
 The point is that the existing translation is equivalent to translating
 via these operators, so with `RebindableSyntax` turned on one could
 translate to those names instead.  Then again, always translating via
 those names would mean less desugaring code, which Simon would approve of.

 (I've edited comment:17 to add the translation of `rec`, which I forgot
 before.)

 > 3. In comment:17 you wrote:
 >
 > {{{
 > do { p <- cmd; stmts } = cmd `bind` \ p -> do { stmts }
 > }}}
 >   Is `\ p -> do { stmts }` a shorthand for "put `p` on the stack and
 desugar `do { stmts }`"? If not, then what does it mean (code as written
 does not typecheck because `bind` needs an arrow, not a lambda).

 Remember that we're still in the command world here, so the infix operator
 `bind` is applied to two commands.  A command can have the form `\ p ->
 cmd`, and that's what we have here.  The meaning follows from the above
 implementation of `bind` and the existing translation rules for commands.
 The `bind`operator will leave the output of the first command on the
 stack, and the second command will take it off and match it against `p` to
 extend its local environment.

 > 4. I assume that this desugaring still requires the stack to store bound
 parameters (`p` in this example)?

 The rules for commands other than `do` and `if` would be as before.  The
 lambda would take the argument off the stack, match it against `p`, and
 add to the local environment an entry for each variable in `p`.

 > Replying to [comment:28 ross]:
 > > I don't see how the former can work, as each language construct is
 translated to several of those combinators.
 >
 > This seems technically simple to me: just store in a constructor as many
 copies of the required combinators as necessary for desugaring. Although
 simple it leads to a design I'm not happy with. For example `RecStmt`
 requires 11 (sic!) combinators to desugar: 5x `>>>`, 4x `arr`, `first` and
 `loop`.
 >
 > > you have less control of the types of these things, because the
 translation re-arranges and trims the environment it passes through the
 arrow.
 >
 > Yes, if I need to write down the exact types for typechecking this
 becomes a problem. Which brings me to another question related to Simon's
 answer:
 >
 > Replying to [comment:29 simonpj]:
 > > The last sentence is terribly important!
 >
 > That's what I suspected. So in the typechecker we type check `pat <-
 rhs; stmt` as if it was `rhs >>= \pat -> stmt` and later in the desugarer
 we actually convert it to such form, right? So if I want to typecheck the
 arrow desugaring I need to typecheck *exactly* the form to which it will
 later be desugared, including all the explicit stacks, etc?

 Yes you do, and that will be harder in the arrow case, because the local
 environment is an explicit input to the resulting arrow, and the desugarer
 feels free to trim unused variables from that environment, which will
 change its type.  It would probably be necessary to force the replacements
 for the arrow combinators to be polymorphic in the environment.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/7828#comment:31>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list