# Polymorphic variant representation

**URL:** <https://discuss.ocaml.org/t/polymorphic-variant-representation/5904>\
**Category:** Learning\
**Created:** [June 3, 2020, 7:26am UTC](https://discuss.ocaml.org/t/polymorphic-variant-representation/5904 "2020-06-03T07:26:32Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![recoules](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/recoules/32/1742_2.png) [@recoules](https://discuss.ocaml.org/u/recoules)\
**Post date:** [June 3, 2020, 7:26am UTC](https://discuss.ocaml.org/t/polymorphic-variant-representation/5904/1 "2020-06-03T07:26:32Z")

</div>

Hi,

I am trying to understand the difference between standard and polymorphic variants in term of memory representation and code optimization.  
So far, what I understood is that:

- standard variants:
  - non parametrized variants are represented as integer, starting from 0 (0x1) with incrementing tag;
  - parametrized variants are represented as memory blocs with a `tag` stored in the header – as a byte, tags start at 0 and range up to 255 (with some reserved values at the end).

- polymorphic variants:
  - non parametrized variants are represented as integer – it is the `hash` of its name;
  - parametrized variants are represented as memory blocs with `tag` 0 and their first field is the `hash` of their name.

I can think about two _drawbacks_ for using polymorphic variants:

- parametrized ones use one more word in memory;
- unlike the `tag` that is bound to small numbers, the `hash` can range from 0 to 2^31+ – some optimization like _pattern matching_ with _jump table_ can not be used, forcing to use a sequence of _if-then-else_.  
Thus, polymorphic variants can end up producing slightly slower running code.

Am I forgetting something or is it all?

Also, I am wondering, as polymorphic variants use `hash` function, is a collision possible for two distinct variants? Theoretically, it is but I am expecting it to be very (very…) rare events.  
Is there, in practice, some ̀hash` properties _by design_, that there is no collision for any string of size lower than X where X is the longest name writable for a variant?

Regards,

---

<div class="post-metadata">

**Author:** ![smolkaj](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/smolkaj/32/266_2.png) [@smolkaj](https://discuss.ocaml.org/u/smolkaj)\
**Post date:** [June 3, 2020, 8:02am UTC](https://discuss.ocaml.org/t/polymorphic-variant-representation/5904/2 "2020-06-03T08:02:03Z")

</div>

> [@recoules](#):
>
> Am I forgetting something or is it all?

This is not really in scope for your question, but another disadvantage of polymorphic variants is that their typing rules are more complicated.

---

<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:** [June 3, 2020, 8:02am UTC](https://discuss.ocaml.org/t/polymorphic-variant-representation/5904/3 "2020-06-03T08:02:13Z")

</div>

There’s an advantage to polymorphic variants that you have not mentioned: you can pass their values from two different types without the cost of a conversion (if the types are compatible).

I don’t know the exact properties of the hash function, but I believe there is a compile-time check that no two variants with the same hashes are used in the same compilation unit (it checks on all variant constructors appearing in types, so even if you have a collision, you will never be able to build a program manipulating both values together). It’s possible that you could observe a collision with the polymorphic comparison on values whose type has been existentially quantified, but that’s not specific to polymorphic variants (you can check that `0` has the same representation as `false` the same way).

---

<div class="post-metadata">

**Author:** ![yallop](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yallop/32/517_2.png) [@yallop](https://discuss.ocaml.org/u/yallop)\
**Post date:** [June 3, 2020, 8:21am UTC](https://discuss.ocaml.org/t/polymorphic-variant-representation/5904/4 "2020-06-03T08:21:40Z")

</div>

> [@recoules](#):
>
> Also, I am wondering, as polymorphic variants use `hash` function, is a collision possible for two distinct variants?

Yes:

```auto
$ ocaml
        OCaml version 4.10.0

# [`squigglier; `premiums];;
Line 1, characters 14-23:
1 | [`squigglier; `premiums];;
                  ^^^^^^^^^
Error: Variant tags `squigglier and `premiums have the same hash value.
       Change one of them.

```

---

<div class="post-metadata">

**Author:** ![recoules](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/recoules/32/1742_2.png) [@recoules](https://discuss.ocaml.org/u/recoules)\
**Post date:** [June 3, 2020, 9:49am UTC](https://discuss.ocaml.org/t/polymorphic-variant-representation/5904/5 "2020-06-03T09:49:57Z")

</div>

> [@smolkaj](#):
>
> This is not really in scope for your question, but another disadvantage of polymorphic variants is that their types rules are more complicated.

It is true, but they allow more flexibility and I expect them to be easier to learn, from a beginner point of view, than GADT.

> [@vlaviron](#):
>
> There’s an advantage to polymorphic variants that you have not mentioned: you can pass their values from two different types without the cost of a conversion (if the types are compatible).

You are right. It is exactly why I am looking for polymorphic variant. In this different topic [Sum types: sub- & super-type](https://discuss.ocaml.org/t/sum-types-sub-super-type/5894), I present two use cases where polymorphic variants perform well but, are maybe too powerful for what I want to do.

> [@yallop](#):
>
> > [@recoules](#):
> >
> > Also, I am wondering, as polymorphic variants use `hash` function, is a collision possible for two distinct variants?
> 
> Yes:

Oh… so it is possible, but is caught by the compilation.  
I am curious, is it an already known collision example, or did you find it just for me? 🙂

---

<div class="post-metadata">

**Author:** ![SkySkimmer](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/skyskimmer/32/1672_2.png) [@SkySkimmer](https://discuss.ocaml.org/u/SkySkimmer)\
**Post date:** [June 3, 2020, 1:30pm UTC](https://discuss.ocaml.org/t/polymorphic-variant-representation/5904/6 "2020-06-03T13:30:03Z")

</div>

> [@recoules](#):
>
> I am curious, is it an already known collision example, or did you find it just for me?

It’s mentioned in [Practical generic programming in OCaml | Proceedings of the 2007 workshop on Workshop on ML](https://dl.acm.org/doi/10.1145/1292535.1292548) (2007)  
See also ["squigglier" ocaml - Google Search](https://www.google.com/search?q=%22squigglier%22+ocaml)
