The following problems arise in the context of a patch for adding support for bigarrays to the ocamlmpi library. I don’t know how to solve the third problem. I have a vague intuition that it is not possible, but I would love to be proved wrong or to really understand why it cannot be done.

You are given a list of operations (e.g., Maximum and Logical-And). All of them apply to integer values but only some of them (e.g., Maximum) apply to floating-point values.

Constraint 1: The operations must be modeled by a single variant type.

Problem 1 (easy): give the signature of a function from an int and any operation to an int.

Problem 2 (harder): give the signature of a function from a float and a floating-point-only operation to a float.

Problem 3 (unknown): give the signature of a function from a list of int, char, or float and an operation to unit. When the list contains floats, only floating-point operations are allowed.

Here is my attempt. It solves problems 1 and 2 but fails to solve problem 3.

```
type _ op =
| Max : [< `Int of int | `Char of char | `Float of float ] op
| Land : [< `Int of int | `Char of char ] op
module type S = sig
val reduce_int: int -> [`Int of int ] op -> int
val reduce_float: float -> [`Float of float] op -> float
val reduce_list: 'a list -> [< `Int of 'a | `Char of 'a | `Float of 'a ] op -> unit
end
module A : S = struct
let reduce_int x op = x
let reduce_float x op = x
let reduce_list s op = ()
end
let _ = A.reduce_int 0 Max (* OK *)
let _ = A.reduce_int 0 Land (* OK *)
let _ = A.reduce_float 0. Max (* OK *)
let _ = A.reduce_float 0. Land (* OK: REJECTED *)
let _ = A.reduce_list [0] Max (* OK *)
let _ = A.reduce_list [0] Land (* OK *)
let _ = A.reduce_list [0.] Max (* OK *)
let _ = A.reduce_list [0.] Land (* KO: NOT REJECTED! *)
```

The problem can be solved using module types if constraint 1 is dropped, but this solution seems more bureaucratic than elegant.

Anyone have a better idea?

Tim.