Perfect! That's exactly what I need. If I use your idea and provide explicit typing for the other two methods everything works fine. My final (working) methods: method private method_12 : 'a. int -> ([> `One | `Two ] as 'a) = function | 1 -> `One | _ -> `Two method method_123 : int -> [ `One | `Two | `Three ] = function | 3 -> `Three | x -> o#method_12 x method method_124 : int -> [ `One | `Two | `Four ] = function | 4 -> `Four | x -> o#method_12 x OCaml gives me the desired types: method private method_12 : 'a. int -> ([> `One | `Two ] as 'a) method method_123 : int -> [ `One | `Three | `Two ] method method_124 : int -> [ `Four | `One | `Two ] Thanks for the quick response, Reed On Sat, Feb 2, 2013 at 4:13 PM, Jeremy Yallop wrote: > On 2 February 2013 23:18, Reed Wilson wrote: > > What I really want is a signature like this: > > method private method_12 : int -> [ > `One | `Two ] > > method method_123 : int -> [ `One | `Two | `Three ] > > method method_124 : int -> [ `One | `Two | `Four ] > > > > If I replace method_12 with a function outside the class it works fine, > but > > for whatever reason method_12 really wants to be the exact same type as > > method_123 and method_124. > > > > Is there any way around this typing requirement for methods? > > I think that the problem arises because methods are typed similarly to > mutually-recursive functions. Unless you give type signatures, both > functions that are marked as mutually recursive and methods are > assumed to be monomorhpic. For example, in > > let rec f = fun x -> x > and g = fun x -> f (x + 1) > > the types are > > val f : int -> int > val g : int -> int > > i.e. f is assigned the type with which it is used in the body of g. > If you remove the (unnecessary) mutual recursion then the more general > types will be inferred; for example, in > > let f = fun x -> x > let g = fun x -> f (x + 1) > > the types are > > val f : 'a -> 'a > val g : int -> int > > It's also possible to ensure that f is assigned the more general type > by using a type signature: > > let rec f : 'a. 'a -> 'a = fun x -> x > and g = fun x -> f (x + 1) > > With objects, the situation is similar, except that you can't mark > methods non-recursive, so you have to give a type signature to avoid > the monomorphising. So > > object (self) > method f = fun x -> x > method g = fun x -> self#f (x + 1) > end > > receives the type > > < f : int -> int; > g : int -> int > > > whereas > > object (self) > method f : 'a. 'a -> 'a = fun x -> x > method g = fun x -> self#f (x + 1) > end > > receives the more general type > > < f : 'a. 'a -> 'a; > g : int -> int > > > In your example you can ensure that the type you want is inferred by > annotating method_12 with a polymorphic signature: > > object (self) > method private method_12 : 'a. int -> ([> `One | `Two] as 'a) = > function > | 1 -> `One > | _ -> `Two > > method method_123 = function > | 3 -> `Three > | x -> self#method_12 x > > method method_124 = function > | 4 -> `Four > | x -> self#method_12 x > end > > Now the inferred types for method_123 and method_125 are distinct: > > < method_123 : int -> [> `One | `Three | `Two ]; > method_124 : int -> [> `Four | `One | `Two ] > > > Hope that helps a bit, > > Jeremy. > -- รง