<discocaml>
<limp.biskit> get to learn a language at the same time
<discocaml>
<lukstafi> "This appendix describes briefly the new features offered in the current version of Objective CAML at the time of this writing, that is. Objective CAML 3.04."
<discocaml>
<limp.biskit> the old logo is adorable
<discocaml>
<Kali> to be honest, i just read the manual
<discocaml>
<Kali> it's not too bad, and it's hard to get a more thorough covering of them
<discocaml>
<lukstafi> It's not pure reference manual, it has some tutorial sections.
bartholin has quit [Quit: Leaving]
Tuplanolla has quit [Quit: Leaving.]
<discocaml>
<barconstruction> Not necessarily the most accessible recommendation but there's a textbook by Benjamin Pierce on advanced topics in programming language theory where he talks about the design of module systems
<discocaml>
<barconstruction>
<discocaml>
<barconstruction> There is a survey by Derek dreyer of the design space in this area too
<discocaml>
<barconstruction> You can also look at the paper by Appel and others which suggests a module system for Java, criticizing Java packages as being insufficient
<discocaml>
<barconstruction> But I'd like to hear if you find anything good and readable on modular programming
<discocaml>
<yawaramin> RWO has a good treatment of modules
<discocaml>
<limp.biskit> a thing i’m finding is that subconsciously i translate a lot of concepts into their OOP equivalent, which i feel is probably going to limit my ability to actually design around modules
<discocaml>
<limp.biskit> if that makes sense
<discocaml>
<barconstruction> To me the main ideas of the ML module system are
<discocaml>
<barconstruction> - implementor-side abstraction, I.e. encapsulation. At the point of implementation, the implementor can control the way the entire rest of the program interacts with the contents of the module. This corresponds to public/private/protected in Java. Furthermore, modules can be nested hierarchically in a tree structure and modules can expose varying amounts of functionality to other modules depending on how far apart they are on the tree
<discocaml>
<barconstruction>
<discocaml>
<barconstruction> the flip side of the coin is client side abstraction, the ability of the client to write code which is generic with respect to an interface. This corresponds to Java interfaces or Haskell typeclasses
<discocaml>
<barconstruction> Good non-oop examples of modules are modules with multiple important types like the key and value type for a data dictionary. Dually, on the client side, Java interfaces are limited by the fact that it's awkward to write interfaces for modules multiple types.
<discocaml>
<barconstruction> Or you could try writing module with two nested submodules which talk to each other but expose very limited functionality / are not visible at all outside the parent module.
<discocaml>
<barconstruction> Also like some distinctions are pretty obvious like the fact that modules are namespaces, so you'll naturally want to collect things with similar functionality together in a module even if the module gets huge. Java classes are not supposed to be more than a few hundred lines and subclasses are uncommon
<companion_cube>
Good stuff is, you can also use classes in ocaml!
<discocaml>
<limp.biskit> ruby has the term ‘god class’ for a behemoth that’s taken on 700 methods for no good reason
<discocaml>
<limp.biskit> ocaml doesn’t seem to have the same problem with modules, partially i think cause it’s easier to write a module with more functionality that’s still got a nice logical separation than in a class where your methods and state are generally bundled
<discocaml>
<limp.biskit> ive been trying to avoid classes atm to force me to utilise modules well
<discocaml>
<limp.biskit> i think that’s resulted in better code than otherwise, even if it’s going outside of my comfort zone
<discocaml>
<limp.biskit> a side effect of that i’ve noticed is that functors sort of spread everywhere through my code in a way that wouldn’t happen under dynamic dispatch
<companion_cube>
I'd say modules are good for structuring the code, anyway; classes are good for late-bound interfaces (eg IO channels)
<companion_cube>
Functors, imho, are best kept small and contained
<companion_cube>
Else they do contaminate a lot of the codebase
<discocaml>
<limp.biskit> basically a ‘god functor’
<discocaml>
<limp.biskit> what i find is that i’m able to keep the functors themselves fairly small or split into multiple “traits”, but then the amount of code i’m able to actually write without relying on one is basically nil