# Local abstract type and polymorphic variant

**URL:** <https://discuss.ocaml.org/t/local-abstract-type-and-polymorphic-variant/8779>\
**Category:** Learning\
**Created:** [November 9, 2021, 9:15am UTC](https://discuss.ocaml.org/t/local-abstract-type-and-polymorphic-variant/8779 "2021-11-09T09:15:57Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![bobot](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bobot/32/198_2.png) [@bobot](https://discuss.ocaml.org/u/bobot)\
**Post date:** [November 9, 2021, 9:15am UTC](https://discuss.ocaml.org/t/local-abstract-type-and-polymorphic-variant/8779/1 "2021-11-09T09:15:57Z")

</div>

I was playing with the typer with some RPC description (a binding for libgrpc and ocaml-protoc-plugin) in OCaml 3.13.1:

```ocaml
  module type Message = sig
    type t
  end

  type 'a feature_availability = ([< `Yes | `No] as 'a)
  (** Used to indicate that a service as some feature or not *)

  module type Rpc = sig
    module Request : Message
    type client_streaming
  end

  type ('req,'cs) service =
    (module Rpc with type Request.t = 'req and
    type client_streaming = 'cs feature_availability)

  let make_service_functions :
    type req cs . (req,([< `Yes | `No] as cs)) service -> _ =
    fun r ->
    let module R = (val r) in
    R.Request.from_proto, R.Response.to_proto

```

I got the typing error:

```ocaml
File "ocaml-protoc-plugin/src/ocaml_protoc_plugin/service.ml", line 37, characters 43-45:
37 | type req cs . (req,([< `Yes | `No] as cs)) servic
                                                ^^
Error: Syntax error

```

Is there some way to type this function?

---

<div class="post-metadata">

**Author:** ![emillon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emillon/32/1206_2.png) [@emillon](https://discuss.ocaml.org/u/emillon)\
**Post date:** [November 9, 2021, 9:37am UTC](https://discuss.ocaml.org/t/local-abstract-type-and-polymorphic-variant/8779/2 "2021-11-09T09:37:42Z")

</div>

`type req cs . ...` is sugar for universal quantification + abstract type variables ([pointer in the manual](https://ocaml.org/manual/locallyabstract.html#p:polymorpic-locally-abstract)) so you can try to unsugar it by hand:

```ocaml
let make_service_functions :
    'req 'cs . ('req,([< `Yes | `No] as 'cs)) service -> _ =
    fun (type req) (type cs) r ->
    ...

```

It’s even possible that you don’t even need the type variables and can remove the `(type req) (type cs)` part.

---

<div class="post-metadata">

**Author:** ![vlaviron](https://avatars.discourse-cdn.com/v4/letter/v/ec9cab/32.png) [@vlaviron](https://discuss.ocaml.org/u/vlaviron)\
**Post date:** [November 9, 2021, 10:50am UTC](https://discuss.ocaml.org/t/local-abstract-type-and-polymorphic-variant/8779/3 "2021-11-09T10:50:21Z")

</div>

I couldn’t get it to work with polymorphic variants, but here is a version that seems to work, with GADTs:

```ocaml
module type Message = sig
  type t
end

type yes = Yes_t
type no = Not_t
type 'a feature_availability =
  | Yes : yes feature_availability
  | No : no feature_availability
  (** Used to indicate that a service as some feature or not *)

module type Rpc = sig
  module Request : Message
  type client_streaming
end

type ('req,'cs) service =
  (module Rpc with type Request.t = 'req and
  type client_streaming = 'cs feature_availability)

let make_service_functions :
  type req cs. (req, cs feature_availability) service -> _ =
  fun r ->
  let module R = (val r) in
  R.Request.from_proto, R.Response.to_proto

```

(this code doesn’t type-check, but for more obvious reasons: `from_proto` is missing from `Request`, and `Response` is missing)

---

<div class="post-metadata">

**Author:** ![bobot](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bobot/32/198_2.png) [@bobot](https://discuss.ocaml.org/u/bobot)\
**Post date:** [November 9, 2021, 1:06pm UTC](https://discuss.ocaml.org/t/local-abstract-type-and-polymorphic-variant/8779/4 "2021-11-09T13:06:01Z")

</div>

The `val r` requires to use local abstract type:

```auto
File "ocaml-protoc-plugin/src/ocaml_protoc_plugin/service.ml", line 61, characters 19-26:
61 | let module R = (val r) in
                        ^^^^^^^
Error: The type of this packed module contains variables:
       ('req, [< `No | `Yes]) service

```

---

<div class="post-metadata">

**Author:** ![bobot](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bobot/32/198_2.png) [@bobot](https://discuss.ocaml.org/u/bobot)\
**Post date:** [November 9, 2021, 1:19pm UTC](https://discuss.ocaml.org/t/local-abstract-type-and-polymorphic-variant/8779/5 "2021-11-09T13:19:58Z")

</div>

Great use of GADT, thank you! I used your solution [[Service] Use a GADT for representing feature availability · bobot/ocaml-protoc-plugin@3ba81c4 · GitHub](https://github.com/bobot/ocaml-protoc-plugin/commit/3ba81c48a22b223e8ae41ac94ae6769308270626)
