Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Syntax improvement for functor type definitions #6039

Closed
vicuna opened this issue Jun 12, 2013 · 8 comments
Closed

Syntax improvement for functor type definitions #6039

vicuna opened this issue Jun 12, 2013 · 8 comments
Assignees

Comments

@vicuna
Copy link

vicuna commented Jun 12, 2013

Original bug ID: 6039
Reporter: @mmottl
Assigned to: @mshinwell
Status: resolved (set by @mshinwell on 2016-12-07T17:05:28Z)
Resolution: fixed
Priority: normal
Severity: feature
Version: 4.00.1
Fixed in version: 4.02.0
Category: ~DO NOT USE (was: OCaml general)
Tags: patch
Monitored by: "Julien Signoles" @hcarty @mmottl

Bug description

Why is it actually that we need to define:

module type Foo = functor (X : sig end) -> sig end

Instead of the syntactically lighter and more intuitive:

module type Foo (X : sig end) = sig end

If a functor takes multiple arguments, we also need to write:

module type Foo = functor (X : sig end) -> functor (Y : sig end) -> ...

Instead of:

module type Foo = functor (X : sig end) (Y : sig end) -> ...

Or the most readable one:

module type Foo (X : sig end) (Y : sig end) = ...

Module definitions in signatures already allow syntax similar to the above:

module Foo (X : sig end) : sig end

Anonymous function definitions also support a more concise syntax:

fun x y -> ...

Instead of having to write:

fun x -> fun y -> ...

This makes the current syntax somewhat irregular when it comes to functor definitions. I'm not sure such a syntax improvement could break backward-compatibility in the parser, but probably not. Maybe a handful of CamlP4 macros might require a fix, but this would likely be straightforward.

File attachments

@vicuna
Copy link
Author

vicuna commented Jun 19, 2013

Comment author: @damiendoligez

Here is a patch against trunk(4.02). Before we commit it, I'll need a review and a discussion about the feature.

I'm a bit worried that this syntax makes it look like we are defining a module type constructor (a mapping from modules to module types) rather than a functor module type (the type of a mapping from modules to modules). If other people think that's not a big problem, we'll apply the patch.

We'll re-launch the discussion after the 4.01.0 release.

@vicuna
Copy link
Author

vicuna commented Jun 19, 2013

Comment author: @mmottl

I see your point concerning the mapping from modules to module types, but there is currently no syntax for implementing the latter anyway. People will usually use workarounds like:

module Make_module_type (Args : ARGS) = struct module type S = sig ... end end

I hence don't think anybody would confuse the new syntax as representing module type constructors. Not saying it wouldn't be nice to have some sort of syntactic sugar for the latter, too, e.g. something of the sort:

module Make_module_type (Args : ARGS) = sig ... end

Then, of course, I might worry about how to avoid ambiguities in signatures.

No rush with this feature, I think improvements to the module system should be carefully discussed. In my experience the module system is already impressively expressive, but a little unwieldy to use at times.

@vicuna
Copy link
Author

vicuna commented Jun 20, 2013

Comment author: @xavierleroy

Waitaminute. I am uncomfortable with the proposed syntactic sugar. Let's make the parallel functor = function. In a signature, a function is declared like this:

val f: int -> bool -> string

What you're proposing is akin to

val f (x: int) (y: bool) = string

First, the "=" makes no sense: this is a declaration, not a definition. But even with "=" replaced by ":"

val f (x: int) (y: bool) : string

I don't see much of an improvement in clarity or otherwise w.r.t.

val f: int -> bool -> string

Going back to functors and the module level, there is already a lot of confusion in some users's minds about definition versus declaration. I'm afraid that making functor declarations "more like" functor definitions isn't going to help.

The one part of the suggestion I can agree with is the curried functor type

functor (X: S1) ... (Y: Sn) -> S

which is indeed syntactically lighter, yet consistent with the view above (declarations should look different from definitions).

@vicuna
Copy link
Author

vicuna commented Jun 20, 2013

Comment author: Julien Signoles

Here are my 2 cents: I agree with Xavier. Also, that's true that "functor ... -> ..." is an heavy syntax and a better one could have been chosen some years ago ;-) but, from my own experience, it is not used very often. The only use case I have in mind is higher-order (uncurried) functors which are pretty rare.

@vicuna
Copy link
Author

vicuna commented Jun 20, 2013

Comment author: @mmottl

@xLeroy: the parallel seems more like a comparison to the signature of functors, which already is:

module F (X : Int) (Y : Int) : String

But the suggestion was to improve definitions of functor module types, which seems conceptually more similar to type definitions. Still, I agree that the "=" looks more like a definition and should hence follow right after the defined name. So how about this:

module type F = (X : Int) -> (Y : Bool) -> String

This basically means just dropping the functor keyword. I don't see why it should ever be useful in a signature anyway. We also don't use "fun" in type definitions:

type f = fun int -> fun bool -> string

A more consistent though minimally longer way to define functors in signatures would then have been (compare to the function definition):

module F : (X : Int) -> (Y : Bool) -> String
val f : int -> bool -> string

The above also seems more suggestive of the fact that currying works with modules, too.

The "functor" keyword would ideally only appear in structures to pass anonymous functors to a higher-order functor as in:

module Res = Apply (functor (X : S) -> struct ... end)

Thinking about what I'd really prefer language-wise, it's probably syntactic consistency rather than utmost syntactic brevity.

The above syntax changes would seem backwards-compatible and cleaner, but I'd admittedly be reluctant to add syntax alternatives that would likely confuse beginners even more. OTOH, their struggles with the module system are probably not so much syntactic anyway so maybe we can at least drop the requirement for the "functor" keyword in module type definitions for a start. It really feels quite unnecessary there.

@vicuna
Copy link
Author

vicuna commented Aug 21, 2014

Comment author: @damiendoligez

Note: the part Xavier agrees with (curried functor types) is now implemented.

@vicuna
Copy link
Author

vicuna commented Aug 21, 2014

Comment author: @mmottl

I've just tried the 4.02 beta, and the new syntax seems to be working fine.

@vicuna
Copy link
Author

vicuna commented Dec 7, 2016

Comment author: @mshinwell

In which case this issue can be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants