[GHC] #5267: Arrow command combinators

GHC cvs-ghc at haskell.org
Sun Nov 6 17:40:37 CET 2011


#5267: Arrow command combinators
----------------------------------------+-----------------------------------
  Reporter:  peteg                      |          Owner:  ross            
      Type:  bug                        |         Status:  new             
  Priority:  normal                     |      Milestone:  7.4.1           
 Component:  Compiler                   |        Version:  7.0.3           
Resolution:                             |       Keywords:                  
  Testcase:                             |      Blockedby:                  
Difficulty:                             |             Os:  Unknown/Multiple
  Blocking:                             |   Architecture:  Unknown/Multiple
   Failure:  GHC rejects valid program  |  
----------------------------------------+-----------------------------------

Comment(by simonpj):

 Ah, I see.  The relevant code is here (line 254 of `TcArrows`:
 {{{
         ; (inst_binds, expr') <- checkConstraints ArrowSkol [w_tv] [] $
                                  escapeArrowScope (tcMonoExpr expr e_ty)

 }}}
 The test is actually still there (it's in `checkConsraints` in fact).  But
 the bug is in `escapeArrowScope`.  This function is rather drastic: it
 replaces the entire typechecker's environment, both local and global, with
 one saved from outside the arrow form.  That is pretty dire, because the
 environment carries more than just what varialbes are in scope.  In
 particular, it carries
   * A mutable cell to collect type checker constraints
   * The index of the youngest "touchable" type variable
 These two help to implement the skolem-escape check, so replacing them
 wholesale amounts to jumping right outside the existential.

 What is `escapeArrowScope` really meant to do?  Here are the comments from
 `TcRnTypes`:
 {{{
 ---------------------------
 -- Arrow-notation context
 ---------------------------

 {-
 In arrow notation, a variable bound by a proc (or enclosed let/kappa)
 is not in scope to the left of an arrow tail (-<) or the head of (|..|).
 For example

         proc x -> (e1 -< e2)

 Here, x is not in scope in e1, but it is in scope in e2.  This can get
 a bit complicated:

         let x = 3 in
         proc y -> (proc z -> e1) -< e2

 Here, x and z are in scope in e1, but y is not.  We implement this by
 recording the environment when passing a proc (using newArrowScope),
 and returning to that (using `escapeArrowScope`) on the left of -< and the
 head of (|..|).
 }}}
 Well if that's all, the task should be handled 100% by the renamer, with
 no need for the type checker to do anything.  Even in the renamer I'm
 suspicious of the lock-stock-and-barrel replacement of the environment.  I
 think all you need do is to snapshot the state of tcl_rdr, and keep that
 in the `ArrowCtxt`, not the entire environment.  Moreover, I think there
 is no need to call `escapeArrowScope` in the typechecker as well as in the
 renamer.  The renamer alone does the job.

 Have I understood aright?

 There is another problem with `TcArrows`, revealed by removing the
 `escapeArrowScope` calls:
 {{{
                 -- Check that it has the right shape:
                 --      ((w,s1) .. sn)
                 -- where the si do not mention w
            ; checkTc (corner_ty `eqType` mkTyVarTy w_tv &&
                       not (w_tv `elemVarSet` tyVarsOfTypes arg_tys))
                      (badFormFun i tup_ty')
 }}}
 You just can't do this with the new type inference engine, because there
 may be many suspended unification constraints so the type might not yet
 have the right shape; only when constraint solving is gone will it have
 the right shape.

 The Right Thing is to unify `corner_ty` with `w_tv`, rather than calling
 `eqType`. But I'm very dubious about the `unscramble` stuff, since it too
 seems to rely on enough unification having taken place.  I don't
 understand this code well enough to sort it out.  Ross, can you see how to
 rewrite it to use unification, or at least functions like
 `matchExpectedListTy` and friends in `TcUinfy`?  Remember that they return
 coercions which must be wrapped around appropriate terms.  I'd be happy to
 dissus by phone or skype if this is obscure.  The basic rule is: you can't
 zonk and then look at the type; I guarantee that will fail as soon as
 things get at all complicated!

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



More information about the Glasgow-haskell-bugs mailing list