* bizarre type
@ 2005-06-30 15:48 Julien Verlaguet
2005-06-30 16:49 ` [Caml-list] " Andreas Rossberg
0 siblings, 1 reply; 11+ messages in thread
From: Julien Verlaguet @ 2005-06-30 15:48 UTC (permalink / raw)
To: caml-list
I would like to know if the following behavior is normal :
type 'a t=string ;;
# let g (x : 'a t) (y : 'a)=();;
val g : 'a t -> 'a -> unit = <fun>
# g ("hello" : int t);;
- : '_a -> unit = <fun>
I was expecting: (int -> unit).
J
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 15:48 bizarre type Julien Verlaguet
@ 2005-06-30 16:49 ` Andreas Rossberg
2005-06-30 16:58 ` Julien Verlaguet
2005-06-30 18:30 ` Julien Verlaguet
0 siblings, 2 replies; 11+ messages in thread
From: Andreas Rossberg @ 2005-06-30 16:49 UTC (permalink / raw)
To: caml-list
Julien Verlaguet wrote:
> I would like to know if the following behavior is normal :
>
> type 'a t=string ;;
>
> # let g (x : 'a t) (y : 'a)=();;
> val g : 'a t -> 'a -> unit = <fun>
>
> # g ("hello" : int t);;
> - : '_a -> unit = <fun>
>
> I was expecting: (int -> unit).
Since
int t = string = '_a t
or more generally,
x t = y t
for any x and y, your type annotation does not induce anything about the
instantiation of g's variable 'a. The following is perfectly legal:
g ("hello" : int t) true
The compiler just infers the most general type.
Cheers,
- Andreas
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 16:49 ` [Caml-list] " Andreas Rossberg
@ 2005-06-30 16:58 ` Julien Verlaguet
2005-06-30 17:16 ` Stephane Glondu
2005-06-30 17:24 ` Andreas Rossberg
2005-06-30 18:30 ` Julien Verlaguet
1 sibling, 2 replies; 11+ messages in thread
From: Julien Verlaguet @ 2005-06-30 16:58 UTC (permalink / raw)
To: Andreas Rossberg; +Cc: caml-list
> The compiler just infers the most general type.
Ok.
But if I write :
# type 'a t;;
type 'a t
# let g (x : 'a t list) (y : 'a)=();;
val g : 'a t list -> 'a -> unit = <fun>
# g ([] : int t list);;
- : int -> unit = <fun>
If I understood well what you just said the inferred type should be :
'_a -> unit
Or is there something I missed there ?
J
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 16:58 ` Julien Verlaguet
@ 2005-06-30 17:16 ` Stephane Glondu
2005-06-30 17:24 ` Andreas Rossberg
1 sibling, 0 replies; 11+ messages in thread
From: Stephane Glondu @ 2005-06-30 17:16 UTC (permalink / raw)
To: caml-list
On Thursday 30 June 2005 09:58, Julien Verlaguet wrote:
> # g ([] : int t list);;
> - : int -> unit = <fun>
I still get '_a -> unit here (I'm using v3.08.3)... However, I also believe
that in both cases, it should be int -> unit.
Stephane Glondu.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 16:58 ` Julien Verlaguet
2005-06-30 17:16 ` Stephane Glondu
@ 2005-06-30 17:24 ` Andreas Rossberg
1 sibling, 0 replies; 11+ messages in thread
From: Andreas Rossberg @ 2005-06-30 17:24 UTC (permalink / raw)
To: caml-list
Julien Verlaguet wrote:
>
> But if I write :
>
> # type 'a t;;
> type 'a t
>
> # let g (x : 'a t list) (y : 'a)=();;
> val g : 'a t list -> 'a -> unit = <fun>
>
> # g ([] : int t list);;
> - : int -> unit = <fun>
>
> If I understood well what you just said the inferred type should be :
>
> '_a -> unit
In this case, t is fully abstract. So int t is only equivalent to
itself, and not to arbitrary x t.
--
Andreas Rossberg, rossberg@ps.uni-sb.de
Let's get rid of those possible thingies! -- TB
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 16:49 ` [Caml-list] " Andreas Rossberg
2005-06-30 16:58 ` Julien Verlaguet
@ 2005-06-30 18:30 ` Julien Verlaguet
2005-06-30 19:37 ` Andreas Rossberg
1 sibling, 1 reply; 11+ messages in thread
From: Julien Verlaguet @ 2005-06-30 18:30 UTC (permalink / raw)
To: Andreas Rossberg; +Cc: caml-list
> for any x and y, your type annotation does not induce anything about the
> instantiation of g's variable 'a. The following is perfectly legal:
>
> g ("hello" : int t) true
>
> The compiler just infers the most general type.
two things :
first
# type 'a t=string;;
type 'a t = string
# let g (x : 'a) (y : 'a t)=();;
val g : 'a -> 'a t -> unit = <fun>
# g 3;;
- : int t -> unit = <fun>
here we should have int t=string='_a t ...
second :
I strongly disaggree with the fact that the compiler infered the most
general type in this case.
Because I specified it.
when you write (let f=fun (x : 'a) (y : 'a) -> (x,y)), you force the type
of x
and y to be equal.
It would be a problem if one could write (f true 3).
J
PS : The behavior with abstract types is the one expected and my example
in the previous mail was irrelevant (sorry about that).
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 18:30 ` Julien Verlaguet
@ 2005-06-30 19:37 ` Andreas Rossberg
2005-06-30 21:42 ` Julien Verlaguet
0 siblings, 1 reply; 11+ messages in thread
From: Andreas Rossberg @ 2005-06-30 19:37 UTC (permalink / raw)
To: caml-list
From: "Julien Verlaguet" <Julien.Verlaguet@pps.jussieu.fr>
>
> # type 'a t=string;;
> type 'a t = string
> # let g (x : 'a) (y : 'a t)=();;
> val g : 'a -> 'a t -> unit = <fun>
> # g 3;;
> - : int t -> unit = <fun>
>
> here we should have int t=string='_a t ...
Well, since '_a t = int t the compiler can freely choose either for
printing. Or bool t, for that matter.
> I strongly disaggree with the fact that the compiler infered the most
> general type in this case.
>
> Because I specified it.
>
> when you write (let f=fun (x : 'a) (y : 'a) -> (x,y)), you force the type
> of x
> and y to be equal.
Yes, but that's not what you did in the other example. You wrote (x : 'a
t) - and because of the way t was defined this was as good as writing (x :
string) and hence did not induce any additional constraint.
Cheers,
- Andreas
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 19:37 ` Andreas Rossberg
@ 2005-06-30 21:42 ` Julien Verlaguet
2005-06-30 23:57 ` Jacques Garrigue
2005-07-03 11:42 ` Damien Doligez
0 siblings, 2 replies; 11+ messages in thread
From: Julien Verlaguet @ 2005-06-30 21:42 UTC (permalink / raw)
To: Andreas Rossberg; +Cc: caml-list
> Well, since '_a t = int t the compiler can freely choose either for
> printing. Or bool t, for that matter.
agreed.
> Yes, but that's not what you did in the other example. You wrote (x : 'a
> t) - and because of the way t was defined this was as good as writing (x :
> string) and hence did not induce any additional constraint.
Ok, I have to aggree.
In fact it prevents me from writting this :
type 'a marshalled=string
let make (x : 'a)=(Marshal.to_string x [] : 'a marshalled);;
And then do all type of operations in a type safe way on strings.
I have to aggree though that I wrote 'a t=string and therefore one should
be able to exchange them.
The only tiny thing that disturbs me is that in my previous example :
let g (x : 'a t) (y : 'a)
the type of y depends on the 'a present in 'a t.
It is odd. But I have to admit it's correct.
Thanks for your help.
J
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 21:42 ` Julien Verlaguet
@ 2005-06-30 23:57 ` Jacques Garrigue
2005-07-03 11:42 ` Damien Doligez
1 sibling, 0 replies; 11+ messages in thread
From: Jacques Garrigue @ 2005-06-30 23:57 UTC (permalink / raw)
To: Julien.Verlaguet; +Cc: caml-list
From: Julien Verlaguet <Julien.Verlaguet@pps.jussieu.fr>
>
> > Well, since '_a t = int t the compiler can freely choose either for
> > printing. Or bool t, for that matter.
>
> agreed.
Nice to see that everybody agrees that the current behaviour is
reasonable :-)
And thanks to Andreas for explaining things so well.
Yet, these useless parameters are a rather weak part of the compiler,
so there may be some bugs left there. I.e. it is hard to guarantee
that "a t" will alway be equivalent to "b t" for any use, while they
should be so in the intended semantics. Bugs report are welcome.
In general, I would suggest avoiding non-abstract phantom types, as
they are useless... except when you're going to abstract them at the
next module boundary.
> In fact it prevents me from writting this :
>
> type 'a marshalled=string
>
> let make (x : 'a)=(Marshal.to_string x [] : 'a marshalled);;
>
> And then do all type of operations in a type safe way on strings.
What you want seems to be the Graal: a type that is more than a
string, but can be implicitly coerced to one. Of course the opposite
direction would not be allowed.
A standard way to do that is to make [marshalled] abstract, and provide
a function [to_string] when you need to recover the string.
In ocaml 3.09, you will have another possibility: using a private type
for that, with the extra advantage of having pattern-matching (this
doesn't work with private types in 3.08, as they are not handled as
abstract.)
But not yet the Graal, which requires to combine implicit subtyping
with type inference in a non-trivial way...
> The only tiny thing that disturbs me is that in my previous example :
>
> let g (x : 'a t) (y : 'a)
>
> the type of y depends on the 'a present in 'a t.
> It is odd. But I have to admit it's correct.
The point here is that ['a t] is not the type of [x] itself, but a
type that can be unified with it. And useless parameters are discarded
during unification. At a more theoretical level, ['a t] is only
required to be equivalent to the type of [x], not identical.
Jacques Garrigue
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-06-30 21:42 ` Julien Verlaguet
2005-06-30 23:57 ` Jacques Garrigue
@ 2005-07-03 11:42 ` Damien Doligez
2005-07-03 12:37 ` Jacques Garrigue
1 sibling, 1 reply; 11+ messages in thread
From: Damien Doligez @ 2005-07-03 11:42 UTC (permalink / raw)
To: caml-list
On Jun 30, 2005, at 23:42, Julien Verlaguet wrote:
> In fact it prevents me from writting this :
>
> type 'a marshalled=string
>
> let make (x : 'a)=(Marshal.to_string x [] : 'a marshalled);;
>
> And then do all type of operations in a type safe way on strings.
If I understand correctly, this is your problem:
Objective Caml version 3.08.3+4 (2005-06-21)
# type 'a marshalled=string;;
type 'a marshalled = string
# let make (x : 'a)=(Marshal.to_string x [] : 'a marshalled);;
val make : 'a -> 'a marshalled = <fun>
# make 1 = make "foo";; (* int marshalled is the same as string
marshalled *)
- : bool = false
It works better you use a concrete type instead of an abbreviation:
# type 'a marsh2 = Marsh of string;;
type 'a marsh2 = Marsh of string
# let make2 (x : 'a) = (Marsh (Marshal.to_string x []) : 'a marsh2);;
val make2 : 'a -> 'a marsh2 = <fun>
# make2 1 = make2 "foo";; (* int marsh2 is not the same as string
marsh2 *)
^^^^^^^^^^^
This expression has type string marsh2 but is here used with type int
marsh2
#
-- Damien
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [Caml-list] bizarre type
2005-07-03 11:42 ` Damien Doligez
@ 2005-07-03 12:37 ` Jacques Garrigue
0 siblings, 0 replies; 11+ messages in thread
From: Jacques Garrigue @ 2005-07-03 12:37 UTC (permalink / raw)
To: caml-list
From: Damien Doligez <damien.doligez@inria.fr>
> If I understand correctly, this is your problem:
>
> Objective Caml version 3.08.3+4 (2005-06-21)
>
> # type 'a marshalled=string;;
> type 'a marshalled = string
> # let make (x : 'a)=(Marshal.to_string x [] : 'a marshalled);;
> val make : 'a -> 'a marshalled = <fun>
> # make 1 = make "foo";; (* int marshalled is the same as string
> marshalled *)
> - : bool = false
>
> It works better you use a concrete type instead of an abbreviation:
>
> # type 'a marsh2 = Marsh of string;;
> type 'a marsh2 = Marsh of string
> # let make2 (x : 'a) = (Marsh (Marshal.to_string x []) : 'a marsh2);;
> val make2 : 'a -> 'a marsh2 = <fun>
> # make2 1 = make2 "foo";; (* int marsh2 is not the same as string
> marsh2 *)
> ^^^^^^^^^^^
> This expression has type string marsh2 but is here used with type int
> marsh2
Actually this is not a very good suggestion from the point of view of
safety, as this useless parameter can still be modified by subtyping:
# make2 1 = (make2 "foo" :> _ marsh2);;
- : bool = false
If you care about safety, you must either use an abstract type, or a
private type in ocaml-3.09 (not 3.08!).
On the other, if you want to keep the possibility of overriding the
parameter, while detecting non-annotated cases, this may actually be a
good approach.
Jacques Garrigue
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2005-07-03 12:37 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-06-30 15:48 bizarre type Julien Verlaguet
2005-06-30 16:49 ` [Caml-list] " Andreas Rossberg
2005-06-30 16:58 ` Julien Verlaguet
2005-06-30 17:16 ` Stephane Glondu
2005-06-30 17:24 ` Andreas Rossberg
2005-06-30 18:30 ` Julien Verlaguet
2005-06-30 19:37 ` Andreas Rossberg
2005-06-30 21:42 ` Julien Verlaguet
2005-06-30 23:57 ` Jacques Garrigue
2005-07-03 11:42 ` Damien Doligez
2005-07-03 12:37 ` Jacques Garrigue
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox