Why doesn't Haskell support mutually recursive modules?
Asked Answered
F

1

18

Haskell supports mutually recursive let-bindings, which is great. Haskell doesn't support mutually recursive modules, which is sometimes terrible. I know that GHC has its .hs-boot mechanism, but I think that's a bit of a hack.

As far as I know, transparent support for mutually recursive modules should be relatively "simple", and it can be done exactly like mutually recursive let-bindings: instead of taking each separate module as a compilation unit, I would take every strongly connected component of the module dependency graph as a compilation unit.

Am I missing something here? Is there any non-trivial reason why Haskell doesn't support mutually recursive modules in this way?

Fatness answered 4/1, 2013 at 1:50 Comment(1)
Haskell does support mutually recursive modules. It's just ghc that doesn't implement them well.Divulgence
M
21

This 6-year-old feature request ticket contains a fair amount of discussion, which you may have already seen. The gist of it is that it's not entirely a simple change as far as GHC is concerned. A few specific issues raised:

  • GHC currently has a lot of baked-in assumptions about how modules are processed during compilation, and changing those assumptions significantly would vastly outweigh the benefits of transparent support for mutually recursive modules.

  • Lumping groups of modules together means they have to be compiled together, which means more recompilation and awkwardness with generating separate .hi and .o files.

  • Backward compatibility with existing builds that use hs-boot files.

  • You have the potential for mutually-recursive bindings that cross module boundaries in a mutually-recursive module group, which raises issues with anything that involves implicit, module-level scope (such as defaulting, and possibly type class instances).

  • And of course, the potential for unknown, unanticipated bugs, as with anything that alters long-standing assumptions in GHC. Even without massive changes to the compilation process, many things are currently assumed to be compiled on a per-module basis.

A lot of people would like to see this supported, but so far nobody has either produced a possible implementation or worked out a detailed, well-specified design that handles all the fiddly corner cases of the sort mentioned above.

Money answered 4/1, 2013 at 2:16 Comment(3)
If I ignore technical debt, backwards compatibility, and established code (which I lumped together as "trivial reasons" ;)), only one issue remains: modules are suddenly not so special anymore, which might cause problems with the type classes. It had crossed my mind, but I really wasn't sure if this would be a problem. Is it currently possible to import symbols, while hiding instances? If not, then an SCC of modules shouldn't be able to define/import conflicting instances anyway, not even with .hs-boot...Fatness
@Tinctorius: In that case, you missed another non-trivial reason, specifically that the people responsible for GHC don't consider those other reasons trivial. :PMoney
And recompilation is indeed an awkward problem. So that's two issues when one would create a compiler from scratch.Fatness

© 2022 - 2024 — McMap. All rights reserved.