Thanks for having the patience to read through my code! That's exactly what I was missing. I did print out the return value in my debug code at some point, but the prettyprinter only shows the suffix of the dictionary variable without the rhs so I totally missed it.

Also, I noticed that simplifyInteractive actually returns an empty bag in the (\x -> x + 1) example I gave, and I actually ended up using the EvBinds returned by simplifyInfer to add the let binding:

    (_, _, evbs, residual, _) <- simplifyInfer tclvl
                                            infer_mode
                                            []
                                            [(fresh_it, res_ty)]
                                            lie
    evbs' <- perhaps_disable_default_warnings $ simplifyInteractive residual

    let full_expr = (mkHsDictLet (EvBinds evbs') (mkHsDictLet evbs tc_expr))

    zonkTopLExpr  full_expr


- Yiyun



On 2/3/20 4:18 AM, Simon Peyton Jones wrote:

In your code (elabRnExpr) you have

 

_ <- perhaps_disable_default_warnings $ simplifyInteractive residual

 

You’ll notice that

simplifyInteractive :: WantedConstraints -> TcM (Bag EvBind)

 

So you are discarding the “evidence bindings” returned by simplifyInteractive.  Those are precisely the bindings of the dictionaries (dictionaries are a form of “evidence”) that you need.  Don’t discard them.

 

Untested:

ev_binds <- perhaps_disable_default_warnings $ simplifyInteractive residual

let full_expr = mkHsDictLet (EvBinds ev_binds) tc_expr

zonkTopLExpr full_expr

 

Simon

 

From: ghc-devs <ghc-devs-bounces@haskell.org> On Behalf Of Yiyun Liu
Sent: 03 February 2020 02:03
To: ghc-devs@haskell.org
Cc: James Parker <jp@jamesparker.me>
Subject: Free dictionary variables in elaborated core expressions

 

Hi ghc-devs,

About 10 days ago, I made a thread about defining a function called elaborateExpr which turns a string into a core expression within an interactive context. Now here's an unexpected behavior which I'm not sure how to deal with.

Given the expression:

(\x -> x + 1) :: Int -> Int

I expect to get something that looks like:

\ (x :: Int) -> + @ Int GHC.Num.$fNumInt x (GHC.Types.I# 1#)

where GHC.Num.$fNumInt is the exported dictionary.

 

What I actually get is something like this:

\ (x :: Int) -> + @ Int $dNum_someuniqueid x (GHC.Types.I# 1#)

where $dNum_someuniqueid is a free dictionary variable within the expression.

 

I was confused by the occurrence of the free variable $dNum at first, but after running the command: "ghc -ddump-ds-preopt somefile.hs" to dump the core bindings, I found that the dictionary variables like $dNum_ are actually local variables defined at the top-level.

My objective is to inline those top-level dictionary definitions into the core expression using let bindings, but it seems tricky since I'm doing everything within an interactive context.  Calling getBindings only gives me the expression I elaborated, but the dictionary is no where to be found.

Interestingly, when I turn on flags such as "DeferTypedHoles" or "DeferOutOfScopeVariables", all the dictionaries are defined locally in let bindings. However, I can't replicate that behavior even with the flags on in the interactive context. How do I find the dictionaries?

Thanks,

- Yiyun