Hello all,
Here's an experience report for porting hoopl to manage MonoLocalBinds. The
Compiler.Hoop.XUtil module has a rather interesting (but probably common) style of code
writing, along the lines of this:
fbnf3 (ff, fm, fl) block = unFF3 $ scottFoldBlock (ScottBlock f m l cat) block
where f n = FF3 $ ff n
m n = FF3 $ fm n
l n = FF3 $ fl n
FF3 f `cat` FF3 f' = FF3 $ f' . f
f, m, l and cat are polymorphic functions that are only used once in the
main expression, and are floated outside to improve readability. However, when
MonoLocalBinds is turned on, these all become monomorphic and the definitions
fail. In contrast, this (uglier) version typechecks:
fbnf3 (ff, fm, fl) block = unFF3 $ scottFoldBlock (ScottBlock (FF3 . ff) (FF3 . fm) (FF3 . fl) (\(FF3 f) (FF3 f') -> FF3 $ f' . f)) block
One suggestion that I had was that we should generalize local bindings that
are only used once, but Marlow pointed out that this would make the typechecker
more complex and I probably would agree.
As a userspace developer, I have two options:
1. Bite the bullet and put in the polymorphic type signatures (which
can be quite hefty)
2. Inline the definitions
3. Move the polymorphic functions into the global namespace
(3) and (2) are not so nice because it breaks the nice symmetry between these
definitions, which always define f, m, l for the many, many definitions in
Hoopl of this style.
Cheers,
Edward