Version française
Home     About     Download     Resources     Contact us    

This site is updated infrequently. For up-to-date information, please visit the new OCaml website at

Browse thread
[Caml-list] Narrowing coercions for functions with optional parameters
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2002-02-25 (01:29)
From: Jacques Garrigue <garrigue@k...>
Subject: Re: [Caml-list] Narrowing coercions for functions with optional parameters
From: Tomasz Zielonka <>

> My original question was: Is is possible to implement narrowing coercions
> for functions with optional parameters. 
> Such coercion would erase optional parameters not found in target type. 
> It is similar to coercing one class to another, when methods not found
> in the target class are hidden/"erased".

There is a common misunderstanding on the meaning of (e :> t).  It
indeed allows some kind of coercion, but it does it by building a
generic subtype of t, which is then unified to the type of e. This
works for records and variants, where you just have to add a row
variable to your type to produce such a generic subtype (yet, it
doesn't really subsume all subtypes, only some of them). This is
impossible with function types: there's no such generic description of
a function with an array of optional parameters.

The alternative is the real coercion notation (e : t1 :> t2). It says
that e has type t1, and you want to coerce it to t2. Then you just
have to compare t1 and t2, to make sure that t1 is a subtype of t2.

It would be possible to coerce functions through the second notation,
but then you bump into the next problem: such coercions would change
the internal representation of the function. This is not the case of
any coercion currently, and this would have strange effects on the
subtyping relation: you can only subtype parts of the type you can
modify. Not really clean.

> When I was preparing an example, it came to me that such coercions are
> sometimes performed automatically:
> We have:
>   val coerce : ('a -> 'b) -> 'a -> 'b = <fun>
>   val g : ?add:int -> int -> int = <fun>
> When 'coerce' is applied to 'g' the type of 'g' must be unified with
> type of 'coerce's argument, that is:
>   ?add:int -> int -> int
> is unified with
>   'a -> 'b
> The only way to do it is to _erase_ optional argument ?add and then
> substitute int for both 'a and 'b.
> So here 'g' was used with type int -> int, optional argument ?add being
> automatically erased. 
> Here the coercion was implicit.

Indeed, you can see it as similar to the implicit coercion to change
parameter order when you apply a labelled function in an order
different from the original one. Here the coercion is only local:
concrete functions are coerced, but for instance you cannot coerce a
list of functions. Moreover it is not triggered by unification, but by
simply examining known types during typing of application, when
the expected function takes only unlabelled arguments.

> So now the question is:
>   Why implicit coercions are performed and explicit coercions are not
>   allowed?

So the answer is: because implicit "coercions" work ok on some
specific syntactical cases, but cannot easily be generalized to full

So, you are stuck with (fun x -> g x), which is in fact shorter than
(g : ?add:int -> int -> int :> int -> int). By the way this is exactly
what [coerce g] does, so you don't loose any efficiency by writing it
explicitly. In fact you may even win some, because coercions have to
be more careful about preserving the semantics, which can mean some
extra cost.


Jacques Garrigue
To unsubscribe, mail Archives:
Bug reports: FAQ:
Beginner's list: