ku-fpg / hermit

Haskell Equational Reasoning Model-to-Implementation Tunnel
http://www.ittc.ku.edu/csdl/fpg/Tools/HERMIT
BSD 2-Clause "Simplified" License
49 stars 8 forks source link

buildDictionaryT fails to find Num and Show dictionaries for Float or Double as superclass constraints. #173

Open conal opened 8 years ago

conal commented 8 years ago

buildDictionaryT fails to find Num and Show dictionaries for Float or Double as superclass constraints. (It yields unbound dictionary variables instead.) It can find Eq and Read dictionaries for Float, Double, and Int, and it can find Num and Show dictionaries for Int. The Num and Show instances for Float and Double are from GHC.Float, while the Eq and Read instances are from GHC.Classes and GHC.Read, respectively. The Num and Show instances for Int are from GHC.Num and GHC.Show, respectively. I've tried adding import GHC.Float () in a module of my plugin and in the examples module given to hermit, but no luck.

Any guesses about what's going wrong here (and possibly all instances from GHC.Float)? Any suggestions for workarounds to try?

RyanGlScott commented 8 years ago

FWIW, I believe this is a GHC issue, not a HERMIT one. Haddock also has trouble locating the Num and Show instances for Float/Double for some inconspicuous reason. (Here's the Haddock ticket.)

conal commented 8 years ago

Thanks for the tip, @RyanGlScott. This is the first time I've tried examples with Double or Float in a HERMIT-based plugin since upgrading from GHC 7.8.2 to 7.10.3.

RyanGlScott commented 8 years ago

Thank makes sense, since the issue probably arose somewhere between 7.8 and 7.10, as GHC has no trouble locating the Num/Show instances for Float in these GHC 7.8-compiled docs for Prelude.

Unfortunately, I never did get a follow-up on that Haddock ticket almost a year later. It might be worth filing as a proper GHC bug now that we've found code outside of Haddock that breaks because of it.

xich commented 8 years ago

Is it because the Num/Show instances are orphan instances for Float/Double? Have you tried to look up any other orphan instances?

conal commented 8 years ago

@xich Sounds like a good guess to me. No, I've not tried to find any other orphans.

xich commented 8 years ago

I'm not sure the fact that they are orphans should mean it is impossible... the typechecker must have some way to deal with orphans, I'm just not sure what it is. It is possible we just aren't initializing the typechecker state from the modguts correctly in HERMIT/GHC/Typechecker.hs.

Figuring out how the typechecker tracks orphans and looking at that file might reveal a fix.

conal commented 8 years ago

Good idea! I'm poking around now in the typechecker to see what I can figure out.

RyanGlScott commented 8 years ago

Indeed, it doesn't appear to be the case that all orphan instances are affected. Two other modules in base (GHC.Base and GHC.Real) export widely used orphan instances like Monoid [a], but they seem to show up just fine in Haddock. I'm not sure what' different about GHC.Float...

conal commented 8 years ago

tcg_visible_orphan_mods seems to be key. It's set to mkModuleSet [mod] in HERMIT.GHC.Typechecker's initTcFromModGuts. In GHC's TcRnDriver module, I see a couple of more complex initializations:

      tcg_visible_orphan_mods = foldl extendModuleSet
                                      (tcg_visible_orphan_mods gbl)
                                      (imp_orphs imports),
     , tcg_visible_orphan_mods = mkModuleSet ic_visible_mods

where

   ; ic_visible_mods <- fmap concat . forM (ic_imports icxt) $ \i ->
        case i of
            IIModule n -> getOrphans n
            IIDecl i -> getOrphans (unLoc (ideclName i))
conal commented 8 years ago

Until we figure this one out, I have a workaround in the form of a newtype wrapper around Double.

conal commented 7 years ago

I'm no longer using HERMIT, but I've continued to run into this problem. Finally, I think I know how to fix it. If it's still an important issue for someone else, I can help.

RyanGlScott commented 7 years ago

@conal: What would it take to fix it? Is this a HERMIT-specific fix, or could it work for the GHC codebase itself?

conal commented 7 years ago

@RyanGlScott I don't know whether there's a fix needed to GHC. In HERMIT.GHC.Typechecker, I think the problem is in the following:

                tcg_imports        = emptyImportAvails,

When I add the module GHC.Float, I'm able to find instances/dictionaries for Num Float etc. For HERMIT, I think you can use

                tcg_imports        = emptyImportAvails { imp_orphs = [ mkModule baseUnitId (mkModuleName "GHC.Float") ] },

where

import Module   ( moduleName, mkModule, mkModuleName, baseUnitId )

I tested this tweak in a copy of HERMIT.GHC.Typechecker, and it fixes the issue for me.

What I'm really doing instead is using GHC's runTcInteractive from TcRnDriver in place of HERMIT's initTcFromModGuts, but first tweaking the given HscEnv env0 to env, defined as follows:

   imports0 = ic_imports (hsc_IC env0)
   orphNames = mkModuleName <$> ["GHC.Float"]
   env = env0 { hsc_IC = (hsc_IC env0) { ic_imports = map IIModule orphNames ++ imports0 } }
RyanGlScott commented 6 years ago

FWIW, Haddock has solved a similar issue with this patch.