The type constraint that you specified does not constraint the polymorphism of the type. To declare a polymorphic constraint, you must use (with OCaml >= 3.12.0) :
let pipe : 'a 'b 'c. ('a, 'b) parzer -> ('c, 'a) parzer -> ('c, 'b) parzer =
fun p1 p2 ->
let p1_rem = ref [] in
fun bs -> match p1 (!p1_rem @ bs) with
| Fail -> Fail
| Wait -> Wait
| Res (res, rem) ->
p1_rem := rem ;
(match p2 [res] with
| Res (res', rem') ->
if rem' <> [] then Printf.printf "WRN: second end of
a pipe did not consume eveything !\n" ;
Res (res', !p1_rem)
| x -> x)
In which case you get the following error :
Error: This definition has type
'a 'b. ('b, 'b) parzer -> ('a, 'b) parzer -> ('a, 'b) parzer
which is less general than
'c 'd 'e. ('e, 'd) parzer -> ('c, 'e) parzer -> ('c, 'd) parzer
Fabrice
On 08/06/2011 02:50 PM, [email protected] wrote:
> Given these types:
>
> (* A parser is given a list of items and returns either a Failure indication,
> a
> Wait for more inputs indication, or a result (composed of a new value and
> the list
> of tokens that were unused) *)
> type ('a, 'b) parzer_result = Wait | Res of ('a * 'b list) | Fail
> type ('a, 'b) parzer = 'b list -> ('a, 'b) parzer_result
>
> And this function used to pipe two parsers together:
>
> (* Use the results of the first parser as the input elements of the second.
> Stop as soon as p2 returns a result or fails.
> Notice that if p1 is a ('a, 'b) parzer and p2 a ('c, 'a) parzer
> then pipe p1 p2 is a ('c, 'b) parzer, which comes handy but p2 is then
> forced to consume everything ! *)
> let (pipe : ('a, 'b) parzer -> ('c, 'a) parzer -> ('c, 'b) parzer) p1 p2 =
> let p1_rem = ref [] in
> fun bs -> match p1 (!p1_rem @ bs) with
> | Fail -> Fail
> | Wait -> Wait
> | Res (res, rem) ->
> p1_rem := rem ;
> (match p2 [res] with
> | Res (res', rem') ->
> if rem' <> [] then Printf.printf "WRN: second end of a
> pipe did not consume eveything !\n" ;
> Res (res', !p1_rem)
> | Fail -> Fail | Wait -> Wait)
>
> This pipe function has the expected type :
>
> # pipe;;
> - : ('a, 'b) parzer -> ('c, 'a) parzer -> ('c, 'b) parzer = <fun>
>
> Now, if I change it's last line for : "| x -> x)", ie not repeating Wait and
> Fail, the result is
> very different :
>
> # pipe;;
> - : ('a, 'a) parzer -> ('b, 'a) parzer -> ('b, 'a) parzer = <fun>
>
> How come?
> And why didn't the compiler complain since I explicitely typed the function
> definition?
>
>
--
Caml-list mailing list. Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs
<<attachment: fabrice_le_fessant.vcf>>
