43

My question is if there is any difference between Standard ML's module system and OCaml module system? Has OCaml all the support of functors , ascriptions etc... that SML has?

Lii
  • 11,553
  • 8
  • 64
  • 88
Dragno
  • 3,027
  • 1
  • 27
  • 41

3 Answers3

57

There are some differences feature-wise, as well as semantically.

Features SML supports but not OCaml:

  • transparent signature ascription
  • module-level let
  • symmetric sharing constraints
  • syntactic sugar for functors over types and values

Features OCaml 4 has but not SML:

  • higher-order functors
  • recursive modules
  • local modules
  • nested signatures
  • modules as first-class values
  • general module sharing (sig with module A = M)
  • module type of

Several SML implementations provide some of these as extensions, however: e.g. higher-order functors (SML/NJ, Moscow ML, Alice ML), local and first-class modules (Moscow ML, Alice ML), module sharing (SML/NJ, Alice ML), nested signatures (Moscow ML, Alice ML), and recursive modules (Moscow ML).

Semantics-wise, the biggest difference is in the treatment of type equivalence, especially with respect to functors:

  • In SML, functors are generative, which means that applying the same functor twice to the same argument always yields fresh types.

  • In OCaml, functors are applicative, which means that applying the same functor twice to the exact same argument (plus additional syntactic restrictions) reproduces equivalent types. This semantics is more flexible, but can also break abstraction (see e.g. the examples we give in this paper, Section 8).

    Edit: OCaml 4 added the ability to optionally make functors generative.

  • OCaml has a purely syntactic notion of signatures, which means that certain type equivalences cannot be expressed by the type system, and are silently dropped.

    Edit: Consider this example:

    module F (X : sig type t end) = struct type u = X.t -> unit type v = X.t end
    module M = F (struct type t = int end : sig type t end)
    

    The type of M is simply sig type u type v end and has thus lost any information about the relation between its types u and v, because that cannot generally be expressed in the surface syntax.

Another notable difference is that OCaml's module type system is undecidable (i.e, type checking may not terminate), due to its permission of abstract signatures, which SML does not allow.

Andreas Rossberg
  • 34,518
  • 3
  • 61
  • 72
  • 4
    I think you should take the opportunity to take a bit about *future* module systems, or more precisely the way these feature sets would change assuming a reasonable inception of the "recent" (mostly yours) research on module systems in a next clean iteration of a ML language. That would turn an very interesting answer into an *extremely* interesting answer. – gasche Mar 23 '13 at 12:43
  • 4
    I felt it inappropriate to piggyback the question for that ;). My personal answer would be pretty much what's in the F-ing modules paper I link above -- it subsumes all of the listed features in a clean and (fairly) simple manner (including both generative and applicative functors), minus recursive modules. For those I'm not so sure. OCaml's recursive modules are far too ad-hoc and limited for my taste, but a comprehensive approach will ultimately lead to abandoning a major part of what makes up ML modules, as we describe in the MixML paper. The jury is still out on whether it's worth that. – Andreas Rossberg Mar 23 '13 at 16:18
  • @AndreasRossberg I am not sure what you mean by abandoning major part ML modules in context of MixML, in the paper you mentioned infact elaborated that ML modules can be seen as end points on MixML spectrum. (Correct me If I am wrong, the basic Idea for building modules was by fibration rather than parameterization) – fedvasu Apr 02 '13 at 13:26
  • 2
    @fedvasu, yes, traditional modules arise as special cases, but yet, the character of the whole system changes quite severely. Traditional ML modules are very functional in nature (e.g. functors as functions, signatures as a natural notion of type). The MixML approach appears less functional and more object-oriented the closer you look, including some of the problems that entails (e.g. more complex, object-like primitives, the hybrid role of modules as both values and types, and observable side effects in initialisation). Question is, is that a bug or a feature? ;) – Andreas Rossberg Apr 02 '13 at 15:16
  • @AndreasRossberg very interesting perspective (and explanation)!! so you are saying Martin Odersky is right about objects? (http://events.inf.ed.ac.uk/Milner2012/M_Odersky-html5-mp4.html) – fedvasu Apr 03 '13 at 00:05
  • @AndreasRossberg So for a ML-like language F-ing modules + some ad-hocy recursive modules are good enough? (your opinion?) – fedvasu Apr 03 '13 at 00:09
  • 2
    @fedvasu, depends on what specific statement from Odersky you are referring to. ;) Re good enough: either no recursion at all (which many people believe is preferable anyway), or bite the bullet and go the whole way to something similar to MixML. All ad-hoc notions of recursive modules I have seen introduce even more problems and/or are too limited to carry their weight IMHO. – Andreas Rossberg Apr 03 '13 at 11:44
  • @AndreasRossberg Regarding Odersky, He particularly mentions Objects as first-class modules,also the (two)slides about Mixin Composition (the scala way) and Functors (ML way) and he also mentions parameterization being subsumed by "abstract members". All these ideas are close to what you describe in MixML paper (They atleast seem so to my untrained eyes!) and Again He mentioned many times (at other places) importance of Objects as mechanism for modularity – fedvasu Apr 03 '13 at 22:40
  • @AndreasRossberg do you feel that MixML style modules are worth their weight to the next-generation ML languages? Also curious about those observable side effects in initialisation (causing many gotchas for OO practitioners). – Steven Shaw Apr 06 '14 at 12:09
  • 1
    @StevenShaw, to be quite honest, I'm still undecided myself. As for side effects, initialisation requires evaluation of respective module bodies, which can generally be effectful computations. Hence, despite recursion, there is a sequential, left-to-right evaluation order that matters for the order of possible effects. Also, you get runtime exceptions when the recursion turns out to be not well-founded, i.e., some value component is used before its initialisation. (Although that's still better than, say, Java, where you just silently get bogus "default" values.) – Andreas Rossberg Apr 27 '14 at 21:41
  • 1
    @AndreasRossberg thanks for your thoughts. I am partial to the idea of ML module systems but others are trying to convince me that they are not worth it. I really like MixML and would like to see it in some kind of modern ML-family language. I'd even like to have something to do with adding such a module system to Idris. – Steven Shaw Apr 28 '14 at 00:42
  • 1
    Anyone know where a reference for SML's syntactic sugar for functors over types and values is? I hadn't heard of that before reading this and am having trouble finding a mention of it anywhere but this post. – Greg Nisbet Sep 23 '15 at 16:43
  • 1
    @GregoryNisbet, see Figure 18 (p.72) of the language Definition (http://sml-family.org/sml97-defn.pdf). In short, the forms _funid(dec)_ and _funid(spec)_ allow you to write e.g. `F(type t)` or `F(type t; val x:t)` when defining a functor, and analogously on application. – Andreas Rossberg Sep 23 '15 at 18:05
2

As for semantics, a much better and elaborate answer is given by Andreas Rossberg above. However, concerning syntax this site might be what you are looking for.

chris
  • 4,988
  • 20
  • 36
0

There is also the abstype facility in SML which is like the datatype facility, except that it hides the structure of the datatype. OCaml relies on module abstraction to do all the hiding that is necessary. Notice that this site does not mention this facility in SML.