# Heterogeneous list using GADTs?

**URL:** https://discuss.ocaml.org/t/heterogeneous-list-using-gadts/4057
**Category:** Learning
**Created:** [July 8, 2019, 5:12am UTC](https://discuss.ocaml.org/t/heterogeneous-list-using-gadts/4057 "2019-07-08T05:12:36Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![MarcCoquand](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/marccoquand/32/4901_2.png) [@MarcCoquand](https://discuss.ocaml.org/u/MarcCoquand)
#### Post date: [July 8, 2019, 5:12am UTC](https://discuss.ocaml.org/t/heterogeneous-list-using-gadts/4057/1 "2019-07-08T05:12:36Z")

</div>

Hello, I’m trying to construct a GADT that is creating two separate values and the goal is that finally the types should match up and be the same. So the GADT has a structure:

```auto
type expr('a,'b) = 
  | Custom(string => option('a)): expr(('a => 'b, 'c), ('b, 'c))
  | Slash(expr(('a, 'b), ('c, 'd)), expr(('c, 'd), ('e, 'f))) // combine two expr
      : expr(('a, 'b), ('e, 'f))
   // ...and a bunch of other cases omitted

```

And the evaluator for expr, which I do like this:

```auto
 let rec evaluator:
    type a b c d.
      (expr((a, b), (c, d)), endpoint(a, b)) => Result.t(endpoint(c, d)) =
          (route, state) => switch (route) { ... }

```

Next up I want to create a way to enforce that eval always creates endpoints of type `endpoint(a,a)`. I can do this by defining a function

```auto
  let completeAttempt:
    type a b c.
      (expr((a, b), (c, c)), endpoint(a, b)) => Result.t(endpoint(c, c)) =
    (route, state) => attempt(route, state);

```

This way I can encode the result with a function `encode: type a. endpoint(a,a) => string`. Now to my question: I want to combine different `endpoint(a,a)`. My first idea is to use a existential wrapper:

```auto
 // Existential wrapper
  type any =
    | Any(expr(_)): any;

 type eval('a, 'b) =
    | OneOf(list(any)): eval('a, Response.t(string));

```

As you notice OneOf takes a list of any expr. However it has no way of knowing if the expression has a type `expr('a,'a)`, meaning that later when I evaluate the expression it will throw a compiler error:

```auto
  let evaluate:
    type a b.
      (eval((a, b), Response.t(string)), endpoint(a, b)) =>
      Response.t(string) =
    (evalExpr, endpoint) =>
      switch (evalExpr) {
      | OneOf(expr) =>
         // It can't verify that p has type ('c,'c), thus it throws an error
        List.map((Any(p)) => completeAttempt(p, endpoint), expr) 
        |> pickFirstSuccess
        |> encode

//...

```

I feel my approach might be wrong. I can also imagine a syntax using some alternative operator instead of a list to construct this and use Either to find the first successful option.

---

<div class="post-metadata">

### Author: ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)
#### Post date: [July 8, 2019, 7:18pm UTC](https://discuss.ocaml.org/t/heterogeneous-list-using-gadts/4057/2 "2019-07-08T19:18:02Z")

</div>

As far as I can see, the type of `eval` that you wanted to write is simply:

```auto
type eval('a) = list(expr('a,'a))

```

It is not clear why you are trying to erase all type information in the current definition of `eval`.
