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

[Caml-list] Constructors are not functions

1 view
Skip to first unread message

Chantal KELLER

unread,
Oct 6, 2009, 8:01:48 AM10/6/09
to caml-list
Dear Ocaml users,

Is there a reason for constructors not to behave like functions? For
instance, one cannot make a partial application from a constructor:

# type foo = | Bar of int;;
type foo = Bar of int
# let foobar = Bar in foobar 17;;
Error: The constructor Bar expects 1 argument(s),
but is applied here to 0 argument(s)

Thanks,
--
Chantal KELLER

_______________________________________________
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

Philippe Wang

unread,
Oct 6, 2009, 8:20:10 AM10/6/09
to Chantal KELLER, caml-list
Hello,

I don't know the actual reason, but I guess it's simply a choice of semantics.

It woud be weird to be able to deconstruct (Bar 42) while not be able
to deconstruct (Bar) as it's not constructed.
I mean we can write (match x with Bar y -> y).
If partial construction were accepted we may like to write
(match x with Bar -> x) but we couldn't because Bar is like a function then.

With type t = A | B of int
what would be the error warning for
(match x with A -> 42 | B -> 43) ?

Well, then I guess the reason is that it would be complicated to
choose some sound enough semantics for partial application of
constructors, since the solution of having to write (fun x -> Bar x)
is much simpler.

If someone has the actual historical explanation, I am also interested.

Cheers,

Philippe Wang

Jon Harrop

unread,
Oct 6, 2009, 8:37:48 AM10/6/09
to caml...@yquem.inria.fr
On Tuesday 06 October 2009 13:19:58 Philippe Wang wrote:
> Hello,
>
> I don't know the actual reason, but I guess it's simply a choice of
> semantics.
>
> It woud be weird to be able to deconstruct (Bar 42) while not be able
> to deconstruct (Bar) as it's not constructed.
> I mean we can write (match x with Bar y -> y).
> If partial construction were accepted we may like to write
> (match x with Bar -> x) but we couldn't because Bar is like a function
> then.
>
> With type t = A | B of int
> what would be the error warning for
> (match x with A -> 42 | B -> 43) ?
>
> Well, then I guess the reason is that it would be complicated to
> choose some sound enough semantics for partial application of
> constructors, since the solution of having to write (fun x -> Bar x)
> is much simpler.

Can you not just say that Bar in an expression is a function (fun x -> Bar x)?

--
Dr Jon Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?e

David Allsopp

unread,
Oct 6, 2009, 8:45:20 AM10/6/09
to Chantal KELLER, caml-list
> Is there a reason for constructors not to behave like functions? For
> instance, one cannot make a partial application from a constructor:

This is how SML handles constructors, Xavier explained the reasons he chose to depart from this in:

http://caml.inria.fr/pub/ml-archives/caml-list/2001/08/47db53a4b42529708647c9e81183598b.en.html

I think it would be possible to simulate the SML behaviour in OCaml using camlp4 (if you assume that for [type foo = Bar of int] that future unbound references to [bar] are interpreted as [fun x -> bar x] instead of an error)


David

David Allsopp

unread,
Oct 6, 2009, 8:47:07 AM10/6/09
to Chantal KELLER, caml-list
David Allsopp wrote:
> > Is there a reason for constructors not to behave like functions?
> > For instance, one cannot make a partial application from a constructor:
>
> This is how SML handles constructors, Xavier explained the reasons he
> chose to depart from this in:
>
> http://caml.inria.fr/pub/ml-archives/caml-
> list/2001/08/47db53a4b42529708647c9e81183598b.en.html
>
> I think it would be possible to simulate the SML behaviour in OCaml
> using camlp4 (if you assume that for [type foo = Bar of int] that
> future unbound references to [bar] are interpreted as [fun x -> bar x]
> instead of an error)

Tsk - [fun x -> bar x] should of course be [fun x -> Bar x]

Gerd Stolpmann

unread,
Oct 6, 2009, 9:14:02 AM10/6/09
to Chantal KELLER, caml-list
Here is the answer:

http://groups.google.com/group/fa.caml/browse_thread/thread/20e96409c5418394/5907e1593a84b03a

Gerd

Am Dienstag, den 06.10.2009, 14:01 +0200 schrieb Chantal KELLER:
> Dear Ocaml users,
>
> Is there a reason for constructors not to behave like functions? For
> instance, one cannot make a partial application from a constructor:
>
> # type foo = | Bar of int;;
> type foo = Bar of int
> # let foobar = Bar in foobar 17;;
> Error: The constructor Bar expects 1 argument(s),
> but is applied here to 0 argument(s)
>
> Thanks,
--

------------------------------------------------------------
Gerd Stolpmann, Bad Nauheimer Str.3, 64289 Darmstadt,Germany
ge...@gerd-stolpmann.de http://www.gerd-stolpmann.de
Phone: +49-6151-153855 Fax: +49-6151-997714
------------------------------------------------------------

Jim Farrand

unread,
Oct 6, 2009, 9:14:47 AM10/6/09
to David Allsopp, caml-list
David Allsopp wrote:

> I think it would be possible to simulate the SML behaviour in OCaml using camlp4 (if you assume that for [type foo = Bar of int] that future unbound references to [bar] are interpreted as [fun x -> bar x] instead of an error)

I believe this is already the behaviour under the revised syntax, so
this is definitely possible.

Regards,
Jim

--
Jim Farrand
E-Mail/Jabber/Google-Talk/MSN: jim.f...@gmail.com
Phone number changed Jun 2009: Now ends 996 (Ask for the rest, delete
the old one!)

Jon Harrop

unread,
Oct 6, 2009, 9:15:25 AM10/6/09
to caml...@yquem.inria.fr
On Tuesday 06 October 2009 13:45:04 David Allsopp wrote:
> > Is there a reason for constructors not to behave like functions? For
> > instance, one cannot make a partial application from a constructor:
>
> This is how SML handles constructors, Xavier explained the reasons he chose
> to depart from this in:
>
> http://caml.inria.fr/pub/ml-archives/caml-list/2001/08/47db53a4b42529708647
>c9e81183598b.en.html
>
> I think it would be possible to simulate the SML behaviour in OCaml using
> camlp4 (if you assume that for [type foo = Bar of int] that future unbound
> references to [bar] are interpreted as [fun x -> bar x] instead of an
> error)

Only if you turned multi-argument type constructors into single-argument ones
taking a tuple, i.e. type definitions like:

type t = Bar of int * int

must become:

type t = Bar of (int * int)

--
Dr Jon Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?e

_______________________________________________

Richard Jones

unread,
Oct 6, 2009, 9:39:11 AM10/6/09
to Jon Harrop, caml...@yquem.inria.fr
On Tue, Oct 06, 2009 at 01:38:20PM +0100, Jon Harrop wrote:
> On Tuesday 06 October 2009 13:19:58 Philippe Wang wrote:
> > Hello,
> >
> > I don't know the actual reason, but I guess it's simply a choice of
> > semantics.
> >
> > It woud be weird to be able to deconstruct (Bar 42) while not be able
> > to deconstruct (Bar) as it's not constructed.
> > I mean we can write (match x with Bar y -> y).
> > If partial construction were accepted we may like to write
> > (match x with Bar -> x) but we couldn't because Bar is like a function
> > then.
> >
> > With type t = A | B of int
> > what would be the error warning for
> > (match x with A -> 42 | B -> 43) ?
> >
> > Well, then I guess the reason is that it would be complicated to
> > choose some sound enough semantics for partial application of
> > constructors, since the solution of having to write (fun x -> Bar x)
> > is much simpler.
>
> Can you not just say that Bar in an expression is a function (fun x -> Bar x)?

This is what standard ML seems to do.

Rich.

--
Richard Jones
Red Hat

Michel Mauny

unread,
Oct 6, 2009, 9:50:38 AM10/6/09
to caml-list
Jim Farrand écrit/writes [06/10/2009 15:14] :
> David Allsopp wrote:
>
>> I think it would be possible to simulate the SML behaviour in OCaml
>> using camlp4 (if you assume that for [type foo = Bar of int] that
>> future unbound references to [bar] are interpreted as [fun x -> bar x]
>> instead of an error)
>
> I believe this is already the behaviour under the revised syntax,

No it is not:

# type t = [ C of int and int ];
type t = [ C of int and int ]
# C;
Error: The constructor C expects 2 argument(s),


but is here applied to 0 argument(s)


-- Michel Mauny

David Allsopp

unread,
Oct 6, 2009, 10:04:18 AM10/6/09
to Jon Harrop, caml...@yquem.inria.fr
Jon Harrop wrote:

> David Allsopp wrote:
> > I think it would be possible to simulate the SML behaviour in OCaml
> > using camlp4 (if you assume that for [type foo = Bar of int] that future
> > unbound references to [bar] are interpreted as [fun x -> bar x] instead of an
> > error)
>
> Only if you turned multi-argument type constructors into single-
> argument ones
> taking a tuple, i.e. type definitions like:
>
> type t = Bar of int * int
>
> must become:
>
> type t = Bar of (int * int)

That's not the case at all - there'd be no reason not to interpret [bar] as [fun x y -> Bar(x, y)] for [Bar of int * int]. What would be hairy in camlp4 would be having to read .cmi files to deal with types defined outside your source file, but that's still not impossible...


David

Jon Harrop

unread,
Oct 6, 2009, 10:50:56 AM10/6/09
to caml...@yquem.inria.fr
On Tuesday 06 October 2009 15:04:02 David Allsopp wrote:
> That's not the case at all - there'd be no reason not to interpret [bar] as
> [fun x y -> Bar(x, y)] for [Bar of int * int].

The reason is that it is a PITA. :-)

--
Dr Jon Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?e

_______________________________________________

Richard Jones

unread,
Oct 6, 2009, 11:24:20 AM10/6/09
to David Allsopp, Jon Harrop, caml...@yquem.inria.fr
On Tue, Oct 06, 2009 at 03:04:02PM +0100, David Allsopp wrote:
> That's not the case at all - there'd be no reason not to interpret
> [bar] as [fun x y -> Bar(x, y)] for [Bar of int * int]. What would be
> hairy in camlp4 would be having to read .cmi files to deal with types
> defined outside your source file, but that's still not impossible...

The devil is in the details. I had a look at this, and because you
don't have access to the command line (eg. -I parameters) you can't
easily find the *.cmi files you need. That is assuming it was easy to
parse the command line (hard to do it reliably) or that you could look
inside *.cmi files (the format is undocumented and release-specific).

It would be so nice to have a macro tool which was aware of types, but
that tool isn't camlp4. There are probably theoretical problems with
this, but having a "give_me_the_type_of (ocaml_subexpression)"
function would be awesome indeed.

Rich.

--
Richard Jones
Red Hat

_______________________________________________

Jérémie Dimino

unread,
Oct 6, 2009, 11:51:10 AM10/6/09
to Chantal KELLER, caml-list
Le mardi 06 octobre 2009 à 14:01 +0200, Chantal KELLER a écrit :
> Dear Ocaml users,
>
> Is there a reason for constructors not to behave like functions? For
> instance, one cannot make a partial application from a constructor:
>
> # type foo = | Bar of int;;
> type foo = Bar of int
> # let foobar = Bar in foobar 17;;
> Error: The constructor Bar expects 1 argument(s),
> but is applied here to 0 argument(s)

This does not answer the question, but you can have function generated
automatically for constructors using camlp4.

I wrote some time ago an extension which add a type-conv type processor
"constructor", so you can write:

type t = Foo of string | Bar of int * int
with constructor

and it automatically generates these two functions:

val foo : string -> t
val bar : int -> int -> t

The extension is available here:
http://darcs.ocamlcore.org/cgi-bin/darcsweb.cgi?r=obus;a=headblob;f=/syntax/pa_constructor.ml

--
Jérémie

Jacques Garrigue

unread,
Oct 6, 2009, 12:31:55 PM10/6/09
to ri...@annexia.org, caml...@yquem.inria.fr
From: Richard Jones <ri...@annexia.org>

> It would be so nice to have a macro tool which was aware of types, but
> that tool isn't camlp4. There are probably theoretical problems with
> this, but having a "give_me_the_type_of (ocaml_subexpression)"
> function would be awesome indeed.

The trouble here is that the type of the subexpression depends on its
context... so that you would need to have already typed the whole
expression to do that. If you are extending the syntax, this is a
rather strong requirement. On the other hand, if you design your
extension so that the program is typable before transforming it, then
it would not be theoretically impossible to have campl4 read the
dumped types and use them for an extra pass. You would still need to
type everything once more after that for safety.

Jacques Garrigue

blue storm

unread,
Oct 6, 2009, 5:55:27 PM10/6/09
to Jérémie Dimino, caml-list
On Tue, Oct 6, 2009 at 5:50 PM, J�r�mie Dimino <jer...@dimino.org> wrote:
> This does not answer the question, but you can have function generated
> automatically for constructors using camlp4.
>
> I wrote some time ago an extension which add a type-conv type processor
> "constructor", so you can write:
>
> The extension is available here:
> http://darcs.ocamlcore.org/cgi-bin/darcsweb.cgi?r=obus;a=headblob;f=/syntax/pa_constructor.ml

I also have an old extension of mine, wich use a slightly different
naming scheme (prepend a "_" instead of uncapitalization), and also
provides destructors for record types :
http://bluestorm.info/camlp4/ty_constr.ml.html

Goswin von Brederlow

unread,
Oct 8, 2009, 8:42:26 AM10/8/09
to David Allsopp, Jon Harrop, caml...@yquem.inria.fr
"David Allsopp" <dra-...@metastack.com> writes:

> Jon Harrop wrote:
>> David Allsopp wrote:
>> > I think it would be possible to simulate the SML behaviour in OCaml
>> > using camlp4 (if you assume that for [type foo = Bar of int] that future
>> > unbound references to [bar] are interpreted as [fun x -> bar x] instead of an
>> > error)
>>
>> Only if you turned multi-argument type constructors into single-
>> argument ones
>> taking a tuple, i.e. type definitions like:
>>
>> type t = Bar of int * int
>>
>> must become:
>>
>> type t = Bar of (int * int)
>
> That's not the case at all - there'd be no reason not to interpret [bar] as [fun x y -> Bar(x, y)] for [Bar of int * int]. What would be hairy in camlp4 would be having to read .cmi files to deal with types defined outside your source file, but that's still not impossible...
>
>
> David

Then what about

type t1 = Bar of int * int
type t2 = Foo of (int * int)

If you treat constructors as functions taking one argument then

t1: int * int -> t1
t2: int * int -> t2

But:

# let x = (1,2);;
val x : int * int = (1, 2)
# Foo(x);;
- : t2 = Foo (1, 2)
# Bar(x);;
Error: The constructor Bar expects 2 argument(s),
but is here applied to 1 argument(s)

As functions "Bar" would have to deconstruct the tuple while "Foo"
uses it directly. And I would rather have curried constructors as in
"Bar 1 : int -> t1".


The difference between t1 and t2 gets lost. I actually hate that you
can write "Bar(1,2)" and "Foo(1,2)" Same problem there. It is unclear
if you pass 2 arguments or a tuple.

This should really be

t1: int -> int -> t1
t2: int * int -> t2

fun x y -> Bar x y
fun (x,y) -> Foo (x,y)

MfG
Goswin

David Allsopp

unread,
Oct 9, 2009, 2:30:10 AM10/9/09
to goswi...@web.de, Jon Harrop, caml...@yquem.inria.fr
Goswin von Brederlow wrote:
<snip>

> Then what about
>
> type t1 = Bar of int * int
> type t2 = Foo of (int * int)
>
> If you treat constructors as functions taking one argument then

But why (so arbitrarily) do this?

> t1: int * int -> t1
> t2: int * int -> t2

If you look at each type definition and choose those most appropriate, then:

t1: int -> int -> t1
t2: int * int -> t2

I don't see your point (but this is pre-coffee!)? The fact that you write
[Bar(1, 2)] for a two-constructor variant tag and [bar 1 2] for a "2
argument" function is just an (occasionally irritating) oddity of the OCaml
syntax - it wouldn't have to affect any derived constructor functions here.

However, the impracticality of importing the types from other interfaces
(see Richard Jones post in this thread) has already revealed that this
couldn't be done transparently in the way I'd initially thought so it's
become a bit of a thought experiment anyway :o)


David

Goswin von Brederlow

unread,
Oct 10, 2009, 2:25:37 AM10/10/09
to David Allsopp, Jon Harrop, caml...@yquem.inria.fr
"David Allsopp" <dra-...@metastack.com> writes:

> Goswin von Brederlow wrote:
> <snip>
>> Then what about
>>
>> type t1 = Bar of int * int
>> type t2 = Foo of (int * int)
>>
>> If you treat constructors as functions taking one argument then
>
> But why (so arbitrarily) do this?

Because that was what the mentioned material said.

>> t1: int * int -> t1
>> t2: int * int -> t2
>
> If you look at each type definition and choose those most appropriate, then:
>
> t1: int -> int -> t1
> t2: int * int -> t2
>
> I don't see your point (but this is pre-coffee!)? The fact that you write
> [Bar(1, 2)] for a two-constructor variant tag and [bar 1 2] for a "2
> argument" function is just an (occasionally irritating) oddity of the OCaml
> syntax - it wouldn't have to affect any derived constructor functions here.

Actualy you do see my point. My point was that the appropriate type
should be used.

> However, the impracticality of importing the types from other interfaces
> (see Richard Jones post in this thread) has already revealed that this
> couldn't be done transparently in the way I'd initially thought so it's
> become a bit of a thought experiment anyway :o)
>
>
> David

MfG
Goswin

blue storm

unread,
Oct 10, 2009, 7:49:35 AM10/10/09
to Jon Harrop, caml...@yquem.inria.fr
On Tue, Oct 6, 2009 at 2:38 PM, Jon Harrop <j...@ffconsultancy.com> wrote:
> Can you not just say that Bar in an expression is a function (fun x -> Bar x)?

Ocaml has a "recursive definition of values" extension that make
syntaxic distinctions between constructors and functions even in an
expression context :
http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc70 .

0 new messages