How to return values of a different type in each branch of a pattern match

Viewed 57

In OCaml, how do I return values of different types in different branches of a pattern match?

Example code:

type t =
  | Int of int
  | Bool of bool

let f x =
  match x with
  | Int i -> i
  | Bool b -> b

However, this will fail with Error: This expression has type bool but an expression was expected of type int.

I tried to fix the problem by using a locally abstract type:

type _ t =
  | Int of int
  | Bool of bool

let f (type a) (x : a t) : a =
  match x with
  | Int i -> i
  | Bool b -> b

However, this does not work either. The error is Error: This expression has type int but an expression was expected of type a.

What did I do wrong? Is it even possible to return a value of a different type in each branch of a pattern match?

1 Answers

The type argument you've given to t isn't actually being constrained by anything, and so the compiler will just infer it to be whatever it encounters first, and complain when it encounters something else later that isn't that.

You need to use a GADT to specify a type for the type argument based on the constructor used:

type _ t =
  | Int: int -> int t
  | Bool: bool -> bool t

The locally abstract type is needed to make the type refinement work, but doesn't do anything in itself. It's the GADT that's doing the work here.

Related