Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] Simple idea for making a function infix

215 views
Skip to first unread message

Keisuke Nakano

unread,
Nov 13, 2006, 2:33:51 AM11/13/06
to caml...@inria.fr
Hi all,

Haskell people sometimes complain about that OCaml cannot make an
arbitrary function infix. For example, they can write (3 `min` 4)
to get the result of (min 3 4) in Haskell. Can we satisfy them
without changing OCaml's syntax?

Here is a simple idea for making a function infix in OCaml.
I hope it will be useful for those who like Haskell's backquote
notation `function_name`.
The idea doesn't require any change of OCaml's syntax.

We use the following two infix operators.

let ( /* ) x y = y x
and ( */ ) x y = x y

Then we can make an infix operator /*f*/ for a binary function f.
For example, using binary functions 'min' and 'max', we can write

3 /*min*/ 4 + 6 /*max*/ 8

to get 11 as 'min 3 4 + max 5 8'. Note that the infix operator
( */ ) may conflict with Num.( */ ) if the Num module is loaded
and opened. You can use other definitions in a similar manner, though.

You have to take care of the precedence. For example,

3 /*min*/ 4 * 6 /*max*/ 8

will return 18 as 'max ((min 3 4) * 6) 8'. So we should write

(3 /*min*/ 4) * (6 /*max*/ 8)

to get 24 as 'min 3 4 * max 6 8'.


The original idea was introduced in my blog a few months ago
(written in Japanese, though). At that time, I used other definitions:

let ( <| ) x y = y x
and ( |> ) x y = x y

or

let ( @^ ) x y = y x
and ( ^@ ) x y z = x z y

where the definition of ( ^@ ) should be given in a different way
because of the precedence of infix operaters starting with '^' or '@'.
These operators perform a different behavior because of the precedences
of operators.

3 <|min|> 4 + 6 <|max|> 8 (* = max (min 3 (4 + 6)) 8 => 8 *)
3 @^min^@ 4 + 6 @^max^@ 8 (* = min 3 (max (4 + 6) 8) => 3 *)

So you have to write

(3 <|min|> 4) + (6 <|max|> 8)
(3 @^min^@ 4) + (6 @^max^@ 8)

to get 11 as min 3 4 + max 5 8'.


Sincerely,

-----------------------------------------------------------------------
Keisuke Nakano
Department of Mathematical Informatics,
University of Tokyo

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Till Varoquaux

unread,
Nov 13, 2006, 11:24:18 AM11/13/06
to Keisuke Nakano
Hi,

I don't really understand the point of the */ operator i your
definition. It's fuy ecause I've cosiderig the same problem recetly ad
came dow to this approach ( I'm redefining(@)... oe c )

Hi,

I don't really understand the point of (*/) in your solution (maybe
for aesthetic
reasons?). Actually, I tried something similar very recently (and
was talking about it a couple of minutes before reading your mail):

( * might interact badly with camlp4 *)
let ($) f a= a f;;

let plus a b= a+b;;

4 $plus 4;;

Jean-Christophe Filliatre

unread,
Nov 13, 2006, 12:50:44 PM11/13/06
to Till Varoquaux

Till Varoquaux writes:
> I don't really understand the point of the */ operator i your
> definition.

I guess it is only aesthetic.

> > We use the following two infix operators.
> > let ( /* ) x y = y x
> >

> It's fuy ecause I've cosiderig the same problem recetly ad
> came dow to this approach ( I'm redefining(@)... oe c )

There is actually an instance of this infix operator in the ocaml
sources (in asmcomp/asmgen.ml for instance). It is used to compose the
various passes of the compiler.

--
Jean-Christophe

skaller

unread,
Nov 13, 2006, 1:05:29 PM11/13/06
to Till Varoquaux
On Mon, 2006-11-13 at 17:19 +0100, Till Varoquaux wrote:
> Hi,
>
> I don't really understand the point of the */ operator i your
> definition. It's fuy ecause I've cosiderig the same problem recetly ad
> came dow to this approach ( I'm redefining(@)... oe c )

> > let ( /* ) x y = y x


> > and ( */ ) x y = x y

The point is precedence: consider only /* then

x /* f y

means

x /* (f y)

whereas

x /* f */ y

means

(f x) y

Of course

x /* f */ y z

means

f x (y z)

but then

x + y z

also means

(+) x (y z)


Also you can write

x /* g h */ y

which means

(g h) x y

which is kind of cute, eg:

[] /* List.fold_left (fun x y -> y::x) */ [1;2;3]


--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net

Till Varoquaux

unread,
Nov 13, 2006, 1:34:08 PM11/13/06
to caml...@inria.fr
First of all, sorry for the garbage on top of my last mail:
my computer hates me

-to Jean Christophe: indeed, that's actually the composition function.....
-to skaller: Hum, I *should* have tested more thoroughly my "solution":

let ( /* ) x y = y x
and ( */ ) x y = x y

let sub = (-)

4 /*sub 5
(* is -1 *)
4 /*sub*/ 5
(* is 1 *)

Regards,

Till

Karl Zilles

unread,
Nov 13, 2006, 3:38:57 PM11/13/06
to Till Varoquaux
Till Varoquaux wrote:
> First of all, sorry for the garbage on top of my last mail:
> my computer hates me
>
> -to Jean Christophe: indeed, that's actually the composition function.....
> -to skaller: Hum, I *should* have tested more thoroughly my "solution":
>
> let ( /* ) x y = y x
> and ( */ ) x y = x y
>
> let sub = (-)
>
> 4 /*sub 5
> (* is -1 *)
> 4 /*sub*/ 5
> (* is 1 *)

You mean exactly the opposite, right?

# 4 /*sub 5
- : int = 1
# 4 /*sub*/ 5
- : int = -1

Pardon if I'm just not keeping up with the conversation.

Till Varoquaux

unread,
Nov 13, 2006, 4:11:11 PM11/13/06
to Karl Zilles
My mistake...

Sorry, seems like I've been very absent minded today...

Till

ol...@pobox.com

unread,
Nov 13, 2006, 11:33:55 PM11/13/06
to caml...@inria.fr

Haskell's back-quote notation has a notable limitation as it applies
to identifiers only. That is, we gain infix identifiers rather than
infix expressions. As it turns out, we can obtain infix expressions
without any change of syntax or any backticks:

http://www.haskell.org/pipermail/haskell-prime/2006-March/000935.html
http://www.haskell.org/haskellwiki/Infix_expressions

It seems that the second solution of the above page is similar to the
one just proposed for OCaml. For ease of comparison, in Haskell, ($) is
defined as [x $ y = x y] and flip flips the order of the arguments.

The first solution on that page can be rendered in Ocaml as follows:

let (>--) x y = (x,y);;
let (<--) (x,f) y = f x y;;

Now we can write

# 3 >-- min <-- 4;;
- : int = 3

We gain not only infix identifiers but infix expressions as well:

let a = Array.make 3 'a';;
val a : char array = [|'a'; 'a'; 'a'|]
1 >-- Array.set a <-- 'b'; a;;
- : char array = [|'a'; 'b'; 'a'|]

so we can use even three-argument functions as sort of `infix'...

0 new messages