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] phantom types and coercions
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2001-10-03 (14:17)
From: Jacques Garrigue <garrigue@k...>
Subject: Re: [Caml-list] phantom types and coercions
From: David Chemouil <>

> we have noticed a strange (at least to us) behavior of the coercion
> operator over phantom types.
> Here is an example:
> # type n = [`Pos];;   (* non-negative number *)
> type n = [ `Pos]
> # type z = [`Neg | `Pos];;   (* integer *)
> type z = [ `Neg | `Pos]
> # type (+'ph) expr = Expr of int;;  (* phantom type *)
> type 'a expr = Expr of int

The problem is that this is not a phantom type. To be more precise, in
ocaml only abstract types behave as phantom types. Citing the
reference manual:

  The variance indicated by the + and - annotations on parameters are
  required only for abstract types. For abbreviations, variant types or
  record types, the variance properties of the type constructor are
  inferred from its definition, and the variance annotations are only
  checked for conformance with the definition.

You can see that the "+" does not appear in the output of the
compiler. In fact 'ph is "anyvariant", since it does not appear in the
type itself.

This behaviour is natural, since you would be able to fool the
compiler by matching Expr, and building a new one.

On the other hand, you can build a small ADT to get a real phantom

module Expr : sig
  type +'a expr
  val pos_expr : int -> [`Pos] expr
  val neg_expr : int -> [`Neg] expr
  val add : 'a expr -> 'a expr -> 'a expr
  val get : 'a expr -> int
end = struct
  type 'a expr = int
  let pos_expr n = if n < 0 then invalid_arg "pos_expr"; n
  let neg_expr n = if n > 0 then invalid_arg "neg_expr"; n
  let add n1 n2 = n1 + n2
  let get n = n

Hope this helps,

Jacques Garrigue
Bug reports:  FAQ:
To unsubscribe, mail  Archives: