caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Documentation challenges for the application of comparison functions
@ 2021-01-02 15:42 Markus Elfring
       [not found] ` <CAHsMTAGtTZ7KaSfUqmPJf6bBmX6uD4==x5U3De66EA7Woq4Hhg@mail.gmail.com>
  0 siblings, 1 reply; 4+ messages in thread
From: Markus Elfring @ 2021-01-02 15:42 UTC (permalink / raw)
  To: caml-list

Hello,

I have taken another look at a few functions of a software library
where comparison functions should be passed.

…
let rec find ~cmp x = function
    Empty -> raise Not_found
  | …

let not_found_default_action ~value ?compare:(cmp=Stdlib.compare) =
    raise Not_found
…


Interface descriptions can be generated then in a known format for OCaml 4.11.1.

…
val find : cmp:('a -> 'b -> int) -> 'a -> ('b, 'c) t -> 'c
val not_found_default_action : value:'a -> ?compare:('b -> 'b -> int) -> 'c
…


Now I find two details interesting for further clarification.

1. The first reference for a comparison function seems to express a need for
   different data types “'a” and “'b” while a single type might be sufficient
   for the comparison function according to the second function.

2. The specification of “Stdlib.compare” looks clear according to the semantics
   for a default parameter in a ML source file while the OCaml arrow representation
   can look more challenging.
   How would you recognise that such a function parameter should be applied
   for comparison calls?

Regards,
Markus

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Documentation challenges for the application of comparison functions
       [not found]   ` <9315a69b-5512-7968-2804-785add2d14ea@web.de>
@ 2021-01-04 12:43     ` Matthew Ryan
  2021-01-04 16:33       ` Markus Elfring
  2021-01-04 16:33       ` Markus Elfring
  0 siblings, 2 replies; 4+ messages in thread
From: Matthew Ryan @ 2021-01-04 12:43 UTC (permalink / raw)
  To: Markus Elfring; +Cc: caml users

[-- Attachment #1: Type: text/plain, Size: 4984 bytes --]

It's not equivalent per se, since you lose the flexibility to call the
function with e.g.

let find_float_int ~(cmp : float -> int -> int) (index : float) (map :
(int, 'c)) =
  find ~cmp index map;;

where 'a = float and 'b = int. However, it is valid -- and arguably
describes the function's contract better -- to narrow the function's type
by combining the type variables:

let find : cmp:('a -> 'a -> int) -> 'a -> ('a, 'b) t = find;;

> It would have been nice if this information can be shared also by the
mailing list.

Apologies, I misclicked reply instead of reply-all. I have copied the list
on this reply, with the earlier messages quoted below.

> Would you get into the mood to add comments for any further evolution
according to
affected software libraries?

I'm happy to discuss or comment on any proposals you have. Please feel free
to tag me @mrmr1993 on GitHub if there are relevant conversations there.

Regards,
Matthew

On Sun, 3 Jan 2021, 15:26 Markus Elfring, <Markus.Elfring@web.de> wrote:

> > For backwards-compatibility reasons, this over-general type is unlikely
> to change, and the compiler has no way otherwise to infer that the ~cmp
> argument represents a comparison. Modifying the definition to
> >
> > let rec find ~(cmp : 'a -> 'a -> int) x = ...
>
> Is it really equivalent to replace the automatically determined type “'b”
> by the type annotation “'a”?
>
> (I assume that it can occasionally be more important to distinguish
> between the specified letters.)
>
>
> > val find : {C : Comparable} ->C.t -> (C.t, 'a) t -> 'a
> >
> > I hope this helps, or is at least informative.
>
> Thanks for such constructive feedback.
>
> It would have been nice if this information can be shared also by the
> mailing list.
> https://sympa.inria.fr/sympa/arc/caml-list/2021-01/
>
>
> Would you get into the mood to add comments for any further evolution
> according to
> affected software libraries?
>
> Example:
> https://github.com/elfring/OTCL/
>
> Regards,
> Markus
>

> On Sun, 3 Jan 2021, 07:54 Matthew Ryan, <matthew@o1labs.org> wrote:
>
> Hello Markus,
>
> OCaml infers the most general type for an expression. For example,
>
> let rec fold_left acc xs ~f =
>   match xs with
>   | [] -> acc
>   | x :: xs -> f acc x
>
> will infer the type
>
> val fold_left : 'a -> 'b list -> f:('a -> 'b -> 'a) -> 'a
>
> where the distinct types for the accumulator and list elements are
> inherently more powerful than if they were unified.
>
> For identifying comparison functions, it could be argued that the type of
> Stdlib.compare is over-general, and perhaps should be
>
> type comparison_result = Lt | Eq | Gt
>
> val compare : 'a -> 'a -> comparison_result
>
> For backwards-compatibility reasons, this over-general type is unlikely to
> change, and the compiler has no way otherwise to infer that the ~cmp
> argument represents a comparison. Modifying the definition to
>
> let rec find ~(cmp : 'a -> 'a -> int) x = ...
>
> and using the heuristic that 'a -> 'a -> int is likely a comparison is
> probably the easiest way to proceed for now.
>
> There is a proposal for modular implicits (and a proposed pull request for
> modular explicits) which may make it easier to infer this in the distant
> future. The syntax there is approximately
>
> module type Comparable = sig
>   type t
>   val compare : t -> t -> int
> end
>
> let rec find {C : Comparable} (x : C.t) = ...
>
> val find : {C : Comparable} ->C.t -> (C.t, 'a) t -> 'a
>
> I hope this helps, or is at least informative.
>
> Regards,
> Matthew
>
> On Sat, 2 Jan 2021, 15:42 Markus Elfring, <Markus.Elfring@web.de> wrote:
>
> Hello,
>
> I have taken another look at a few functions of a software library
> where comparison functions should be passed.
>
> …
> let rec find ~cmp x = function
>     Empty -> raise Not_found
>   | …
>
> let not_found_default_action ~value ?compare:(cmp=Stdlib.compare) =
>     raise Not_found
> …
>
>
> Interface descriptions can be generated then in a known format for OCaml
> 4.11.1.
>
> …
> val find : cmp:('a -> 'b -> int) -> 'a -> ('b, 'c) t -> 'c
> val not_found_default_action : value:'a -> ?compare:('b -> 'b -> int) -> 'c
> …
>
>
> Now I find two details interesting for further clarification.
>
> 1. The first reference for a comparison function seems to express a need
> for
>    different data types “'a” and “'b” while a single type might be
> sufficient
>    for the comparison function according to the second function.
>
> 2. The specification of “Stdlib.compare” looks clear according to the
> semantics
>    for a default parameter in a ML source file while the OCaml arrow
> representation
>    can look more challenging.
>    How would you recognise that such a function parameter should be applied
>    for comparison calls?
>
> Regards,
> Markus
>
>

[-- Attachment #2: Type: text/html, Size: 8333 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Documentation challenges for the application of comparison functions
  2021-01-04 12:43     ` Matthew Ryan
  2021-01-04 16:33       ` Markus Elfring
@ 2021-01-04 16:33       ` Markus Elfring
  1 sibling, 0 replies; 4+ messages in thread
From: Markus Elfring @ 2021-01-04 16:33 UTC (permalink / raw)
  To: Matthew Ryan; +Cc: caml-list

> It's not equivalent per se, since you lose the flexibility to call the function with e.g.
>
> let find_float_int ~(cmp : float -> int -> int) (index : float) (map : (int, 'c)) =
>   find ~cmp index map;;

I guess that there is the detail to reconsider if comparisons should be performed
with different data types (which corresponding to special properties of
such a programming interface).


> where 'a = float and 'b = int. However, it is valid

Thanks for such a view.


> -- and arguably describes the function's contract better -- to narrow the function's type by combining the type variables:

I would interpret involved aspects in further directions.


> let find : cmp:('a -> 'a -> int) -> 'a -> ('a, 'b) t = find;;

The elements of a data container like “Map” should usually refer to the same data type,
shouldn't they?

I am curious then under which circumstances a type like “Comparable” can be applied instead.
Will any “…able” types become more popular?

Regards,
Markus

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Documentation challenges for the application of comparison functions
  2021-01-04 12:43     ` Matthew Ryan
@ 2021-01-04 16:33       ` Markus Elfring
  2021-01-04 16:33       ` Markus Elfring
  1 sibling, 0 replies; 4+ messages in thread
From: Markus Elfring @ 2021-01-04 16:33 UTC (permalink / raw)
  To: Matthew Ryan; +Cc: caml-list

> It's not equivalent per se, since you lose the flexibility to call the function with e.g.
>
> let find_float_int ~(cmp : float -> int -> int) (index : float) (map : (int, 'c)) =
>   find ~cmp index map;;

I guess that there is the detail to reconsider if comparisons should be performed
with different data types (which corresponding to special properties of
such a programming interface).


> where 'a = float and 'b = int. However, it is valid

Thanks for such a view.


> -- and arguably describes the function's contract better -- to narrow the function's type by combining the type variables:

I would interpret involved aspects in further directions.


> let find : cmp:('a -> 'a -> int) -> 'a -> ('a, 'b) t = find;;

The elements of a data container like “Map” should usually refer to the same data type,
shouldn't they?

I am curious then under which circumstances a type like “Comparable” can be applied instead.
Will any “…able” types become more popular?

Regards,
Markus

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-01-04 16:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-02 15:42 [Caml-list] Documentation challenges for the application of comparison functions Markus Elfring
     [not found] ` <CAHsMTAGtTZ7KaSfUqmPJf6bBmX6uD4==x5U3De66EA7Woq4Hhg@mail.gmail.com>
     [not found]   ` <9315a69b-5512-7968-2804-785add2d14ea@web.de>
2021-01-04 12:43     ` Matthew Ryan
2021-01-04 16:33       ` Markus Elfring
2021-01-04 16:33       ` Markus Elfring

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).