Please make more use of the qualified ID syntax! Haskell has had this feature for quite some time now, but I hardly ever see it used ...
Especially in modules that import a lot of other modules, it's
- easier to recognize an identifier if it's prefixed by a module ID rather than look through all the imported modules, and
- easier to modify a module if all you need to do to pull in a new value is to use it, rather than scrolling up, and adding it to the list of identifiers in something like .import M (...)
This is standard practice in both SML and Ocaml.(In fact, I would rather not have to declare things like
If you have a long module name, declare an alias:
BTW, another advantage of this syntax is that identifiers within their own defining module get shorter, and consequently it gets easier to read.For example, don't define
Sometimes this means having to hide Prelude identifiers and qualify them at use(as it would be with
but is that such a great price to pay...?
Please. Pretty please? Pretty please with sugar on top?
P.S. Except infix combinators. These are ugly when you qualify them.
One good example of qualified names, one of the Base64 modules has functions named encode and decode. Those are the most sensible names, but are very likely to clash or shadow other functions if directly imported. If you
I use this extensively in an even more rigorous way. In the style of Modula-3 I define one data type or one type class per module. The module is named after the implemented type or class.Then a type is named
This style also answers the annoying question whether the module name should be in singular or plural form: Always choose singular form!
- is going to confuse the heck out of those like myself who still think in Lisp sometimes. WouldConsbe ok instead? -- BartMasseyCon
- I thought the similarity to LISP is good. -- HenningThielemann
Many functions can be considered as conversions.So I define functions like
This way I can import all modules qualified, avoiding name clashes and I can provide a consistent naming through all modules.
The big question remains: In which module shall the conversions reside?Translated to our example: Shall it be
I suggest the following: Find out which module is the general one, and which is the more specific one. I consider the more specific module as an extension to the general module. When you write a general module you cannot predict all possible extensions. That's why you should put all conversions into the extension modules. How to find out which module is more specific?Imagine module A and module B still don't contain any conversion routine between
If module B imports A, then B is the more specific one. Put all conversions between A and B into B. If module A and B are mutually recursive or don't import each other, then rethink if one or the other is the more specific one.If they are on the same level of generality you may add a new module dedicated to conversion between