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
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
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
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
Tsk - [fun x -> bar x] should of course be [fun x -> Bar x]
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
------------------------------------------------------------
> 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!)
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
_______________________________________________
This is what standard ML seems to do.
Rich.
--
Richard Jones
Red Hat
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
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
The reason is that it is a PITA. :-)
--
Dr Jon Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?e
_______________________________________________
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
_______________________________________________
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
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
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
> 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
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 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
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 .