ocamllabs / ocaml-modular-implicits

OCaml extended with modular implicits
Other
103 stars 8 forks source link

Instances should be associated to specific classes #25

Closed charguer closed 9 years ago

charguer commented 9 years ago

(* a first class *)

module type Foo = sig type t val f : t -> t end

implicit module Foo_int = struct (* I'd like to specify that this is an instance for Foo *) type t = int let f x = x + 1 end

let foo_f (implicit P : Foo) x = P.f x

(* a first use case for foo *)

let a = foo_f 1

(* another, completely unrelated class *)

module type Bar = sig (* I'd like to specify that this is an instance for Bar *) type t val f : t -> t end

implicit module Bar_int = struct type t = int let f x = x + 2 end

let bar_f (implicit P : Bar) x = P.f x

(* now, a second use case for foo *)

let b = foo_f 1

(* I think there is a big modularity problem, here. the "implicit" instances should be tagged with the class to which they belong. Being isomorphic is not in my opinion the good criteria for belonging to the same class. *)

lpw25 commented 9 years ago

Module types are structural not nominative, and this behaviour is consistent with that. The members of your module type should distinguish it from other module types.

You can achieve nominative behaviour using the following:

type foo

module type Foo = sig
  type kind = foo
  [...]
end

type bar

module type Bar = sig
  type kind = bar
  [...]
end

I also hope to at some point (probably before modular implicits) add private module types to OCaml (essentially the same as private types but for modules), which allows you to get nominative behaviour for module types.

charguer commented 9 years ago

Sounds great! Btw, do you have an up-to-date tutorial / collection of examples that covers (among other things) the nominative encoding?

lpw25 commented 9 years ago

Btw, do you have an up-to-date tutorial / collection of examples that covers (among other things) the nominative encoding?

I'm afraid not, it's definitely on the todo list, but probably won't get done for quite a while. The abstract from OCaml 2014 outlines basic usage but is quite short.

charguer commented 9 years ago

... and it does not mention the nominal vs structural matching, leaving me to believe that the approach could not work; now that I understand it, I find your proposal much more appealing.

If not writing a tutorial, I would suggest at the very least preparing an example module that shows how to set up proper overloading for all the basic arithmetic operators that every one would want to see overloaded (+, -, *, /, and perhaps also abs and mod). ---I say "everyone", assuming that inlining works well enough for this to be zero-cost. This module would have both direct practical application, and could serve as a little demo of your patch.

Btw, I would strongly encourage having one class per operator, instead of a "Num" class that tries to do everything at once. The reason is that the user may want to overload "+" on types (e.g. strings) where other operators don't make sense. Note that "Num" can be set up as a functor so as to allow providing instances for several operators at once, although in practice I don't think it's a big deal, plus it would require functor inlining to work to avoid the overhead.

Don't hesitate to let me know if you need help with such a library. + Arthur

lpw25 commented 9 years ago

If not writing a tutorial, I would suggest at the very least preparing an example module that shows how to set up proper overloading for all the basic arithmetic operators that every one would want to see overloaded (+, -, *, /, and perhaps also abs and mod). ---I say "everyone", assuming that inlining works well enough for this to be zero-cost. This module would have both direct practical application, and could serve as a little demo of your patch.

I agree that this is a very good idea. Fred had started some examples which I extracted to form the basis of an example library for implicits: https://github.com/ocamllabs/imp. I haven't had a chance to look at them since then, but would definitely appreciate help/pull requests for that.

If you do have a look at improving "Imp" feel free to experiment with the appropriate style because how best to use implicits in libraries is still something that we are working out as we go. Also feel free to suggest removing or adding modules to the library.

There may also be some things in the testsuite which could be useful to look at to see how implicits work.

Btw, I would strongly encourage having one class per operator, instead of a "Num" class that tries to do everything at once. The reason is that the user may want to overload "+" on types (e.g. strings) where other operators don't make sense. Note that "Num" can be set up as a functor so as to allow providing instances for several operators at once, although in practice I don't think it's a big deal, plus it would require functor inlining to work to avoid the overhead.

I agree, I think the Num typeclass in Haskell is generally considered a mistake for similar reasons.

Don't hesitate to let me know if you need help with such a library.

Issues and pull requests to both this repository or the Imp repository are extremely welcome. Feel free to raise issues for questions as well as bugs.