# Polymorphic variant being generalised

**URL:** <https://discuss.ocaml.org/t/polymorphic-variant-being-generalised/6083>\
**Category:** Community\
**Tags:** ocaml\
**Created:** [July 12, 2020, 10:45pm UTC](https://discuss.ocaml.org/t/polymorphic-variant-being-generalised/6083 "2020-07-12T22:45:50Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![BikalGurung](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bikalgurung/32/5105_2.png) [@BikalGurung](https://discuss.ocaml.org/u/BikalGurung)\
**Post date:** [July 12, 2020, 10:45pm UTC](https://discuss.ocaml.org/t/polymorphic-variant-being-generalised/6083/1 "2020-07-12T22:45:51Z")

</div>

Hi,  
I am trying to make the following compile.

```auto
$ cat hello.mli 
type error = [`Msg of string]
val to_string : int -> (string, [> `Msg of string]) result
val f : int -> (string -> ('a, [> error]) result) -> ('a -> 'b) -> ('b, [> error]) result

```

```auto
$ cat hello.ml
type error = [`Msg of string]

let to_string i = 
  if i < 10 then Result.ok (string_of_int i) else Result.error (`Msg "invalid number")

let f : int -> (string -> ('a, [> error]) result) -> ('a -> 'b) -> ('b, [> error]) result = 
  fun i f1 f2 -> Result.bind (to_string i) (fun s -> f1 s) |> function 
    | Ok a -> Ok (f2 a) 
    | Error e -> Error e 

```

However, I keep getting the following compilation error,

```auto
Values do not match:
       val f : int -> (string -> ('a, [> error] as 'c) result) -> ('a -> 'b) -> ('b, 'c) result
       is not included in
       val f : int -> (string -> ('a, [> error]) result) -> ('a -> 'b) -> ('b, 'c) result

```

It seems the ocaml compiler generalizes (?) `[> error]` to `'c` which makes it not compile to the given `hello.mli` file. Is there a way to fix this without changing the signature?

Also does `'c` still conform to ` [> error]` after it being generalized to `'e`?

---

<div class="post-metadata">

**Author:** ![jjb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jjb/32/2713_2.png) [@jjb](https://discuss.ocaml.org/u/jjb)\
**Post date:** [July 12, 2020, 11:10pm UTC](https://discuss.ocaml.org/t/polymorphic-variant-being-generalised/6083/2 "2020-07-12T23:10:22Z")

</div>

The inferred type of `f` indicates that if the `f1` argument returns more than the tags in `error`, then so will `f` itself. The `'c` type variable is expressing that relationship. The type without it is not correct. You either need to constrain `f1` by removing `<` or constrain `f` with `'c`.

---

<div class="post-metadata">

**Author:** ![gasche](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/gasche/32/4_2.png) [@gasche](https://discuss.ocaml.org/u/gasche)\
**Post date:** [July 13, 2020, 7:49am UTC](https://discuss.ocaml.org/t/polymorphic-variant-being-generalised/6083/3 "2020-07-13T07:49:27Z")

</div>

@jjb’s reply is excellent, but let’s give a couple extra details. Your example boils down to something like:

```auto
apply : (unit -> [> error]) -> [> error])

```

When you write `[> error]`, you have to understand this as a universal quantification: an instance of `[> error]` is any type which contains at least `error` (for example `[error]` or `[error | `Foo | `Bar]`. As with polymorphic type variables in signature, the caller gets to choose the instance they want at function application time. The two separate occurrences of `[> error]` correspond to two distinct/independent quantifications.

So the caller could instantiate this to, for example:

```auto
apply : (unit -> [error | `Foo]) -> [error | `Bar]

```

and clearly this is incorrect (with the “obvious” implementation `fun f -> f ()`): if the function parameter returns ` `Foo`, then the return type must allow ` `Foo`. In other words, the two occurrences of `[> error]` must be instantiated with the same type. This corresponds to the following, less general (and more correct) signature:

```auto
val apply : (unit -> ([> error] as 'a)) -> ([> error] as 'a)

```

which can also be written

```auto
val apply : (unit -> ([> error] as 'a)) -> 'a

```

---

<div class="post-metadata">

**Author:** ![BikalGurung](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bikalgurung/32/5105_2.png) [@BikalGurung](https://discuss.ocaml.org/u/BikalGurung)\
**Post date:** [July 13, 2020, 10:02am UTC](https://discuss.ocaml.org/t/polymorphic-variant-being-generalised/6083/4 "2020-07-13T10:02:39Z")

</div>

Thanks. This clarifies it.

I tried some examples in `utop` and it seems to work, i.e. `'a` in `val apply : (unit -> ([> error] as 'a)) -> 'a` restricts instances of `'a` to `[>error]`.

For posterity, here is the sample usage of the function `apply`.

```auto
utop # apply (fun () -> `Foo);;
- : [> error] = `Foo

```

```auto
utop # apply (fun () -> `Bar);;
- : [> `Bar | `Foo] = `Bar

```

```auto
utop # apply (fun () -> "hello");;
Line 1, characters 17-24:
Error: This expression has type string but an expression was expected of type
         [> error]

```

```auto
utop # apply (fun () -> 222);;
Line 1, characters 17-20:
Error: This expression has type int but an expression was expected of type
         [> error]

```

```auto
utop # apply (fun () -> `AAA);;
- : [> `AAA | `Foo] = `AAA

```
