Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Match Comparison OCaml

I have come to love this syntax in OCaml

match myCompare x y with
|Greater->
|Less->
|Equal->

However, it needs 2 things, a custom type, and a myCompare function that returns my custom type.

Would there be anyway to do this without doing the steps above?

The pervasives module seems to have 'compare' which returns 0 if equal, pos int when greater and neg int when less. Is it possible to match those? Conceptually like so (which does not compile):

match myCompare x y with
| (>0) ->
| (0)  ->
| (<0) ->

I know I could just use if statements, but pattern matching is more elegant to me. Is there an easy (if not maybe standard) way of doing this?

like image 799
Secret Avatar asked Aug 24 '13 07:08

Secret


2 Answers

Is there an easy … way of doing this?

No!

The advantage of match over what switch does in another language is that OCaml's match tells you if you have thought of covering all the cases (and it allows to match in-depth and is compiled more efficiently, but this could also be considered an advantage of types). You would lose the advantage of being warned if you do something stupid, if you started using arbitrary conditions instead of patterns. You would just end up with a construct with the same drawbacks as a switch.

This said, actually, Yes!

You can write:

match myCompare x y with
| z when (z > 0) -> 0
| 0 -> 0
| z when (z < 0) -> 0

But using when makes you lose the advantage of being warned if you do something stupid.

The custom type type comparison = Greater | Less | Equal and pattern-matching over the three only constructors is the right way. It documents what myCompare does instead of letting it return an int that could also, in another language, represent a file descriptor. Type definitions do not have any run-time cost. There is no reason not to use one in this example.

like image 105
Pascal Cuoq Avatar answered Sep 21 '22 22:09

Pascal Cuoq


You can use a library that already provide those variant-returning compare functions. This is the case of the BatOrd module of Batteries, for example.

Otherwise your best bet is to define the type and create a conversion function from integers to comparisons.

type comparison = Lt | Eq | Gt
let comp n =
  if n < 0 then Lt
  else if n > 0 then Gt
  else Eq

(* ... *)

match comp (Pervasives.compare foo bar) with
  | Lt -> ...
  | Gt -> ...
  | Eq -> ...
like image 36
gasche Avatar answered Sep 19 '22 22:09

gasche