# Sum type constructor declaration subtlety (and documentation wanted!)

**URL:** <https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898>\
**Category:** Ecosystem\
**Created:** [April 23, 2018, 3:45pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898 "2018-04-23T15:45:42Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [April 23, 2018, 3:45pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/1 "2018-04-23T15:45:42Z")

</div>

Howdy! On the discord channel this morning, someone brought up the fact that in

```auto
type foo = 
| A of int*int
| B of (int*int)

```

that `A` and `B` are quite different. `A` is a constructor taking two arguments, even though it looks like it takes a tuple, while `B` actually takes a tuple.

This means that the two cannot be used interchangeably and in fact have different enough meanings to matter in a lot of contexts.

(This is confusing to a beginner because it would seem like the parentheses are just meaningless precedence grouping, but they aren’t, they’re syntactically quite significant, and it would seem like the `*` in the `A` case means “tuple” but it does not.)

I didn’t know about this distinction myself. I haven’t been using OCaml that long, but it has been long enough that I was surprised I never understood this difference before. It is not well explained in the documentation (or perhaps I simply missed it being pointed out), and it would probably be good to be much more explicit in the official manual, and for books like **RWO** to mention this prominently for beginners.

---

<div class="post-metadata">

**Author:** ![Yaron\_Minsky](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yaron_minsky/32/11_2.png) [@Yaron\_Minsky](https://discuss.ocaml.org/u/Yaron_Minsky)\
**Post date:** [April 23, 2018, 4:50pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/2 "2018-04-23T16:50:22Z")

</div>

Yeah, this deserves a mention in RWO. I’ll put it on the list…

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [April 23, 2018, 5:17pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/3 "2018-04-23T17:17:40Z")

</div>

One thing @bluddy noted during the discussion which was valuable for having it click in my head: if constructors had function types a la Haskell, then the obvious distinction is:

`A: int -> int -> foo`  
while  
`B: (int * int) -> foo`

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [April 23, 2018, 9:09pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/4 "2018-04-23T21:09:36Z")

</div>

I filed an issue on this btw: [https://caml.inria.fr/mantis/view.php?id=7783](https://caml.inria.fr/mantis/view.php?id=7783)

---

<div class="post-metadata">

**Author:** ![n4323](https://avatars.discourse-cdn.com/v4/letter/n/97f17d/32.png) [@n4323](https://discuss.ocaml.org/u/n4323)\
**Post date:** [April 24, 2018, 9:20am UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/5 "2018-04-24T09:20:24Z")

</div>

See also here: [Constructors with several arguments](https://discuss.ocaml.org/t/constructors-with-several-arguments/764/3?u=n4323) .  
The ‘revised syntax’ tried to fix that. I wonder what Reason does here?

---

<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:** [April 24, 2018, 11:40am UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/6 "2018-04-24T11:40:10Z")

</div>

This sounds like a good idea, I think it should be possible to a small paragraph at the end of the [variants and records](http://caml.inria.fr/pub/docs/manual-ocaml/coreexamples.html#sec11) section of the manual.

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [April 24, 2018, 1:04pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/7 "2018-04-24T13:04:07Z")

</div>

> [@octachron](#):
>
> I think it should be possible to a small paragraph at the end of the variants and records section of the manual.

That would seem like the right location. I’d propose something like the following language:

> Note that although the syntax is almost the same, there is a significant difference between a variant constructor that takes multiple arguments and one that takes a single tuple as an argument. Consider the following type:
> 
> ```auto
> type foo = 
> | A of int*int
> | B of (int*int)
> 
> ```
> 
> Although the syntax for `A` and `B` seems nearly the same, the parentheses are quite significant. `A` is a constructor that takes two arguments, both of which are integer typed values, while `B` is a constructor that takes a single argument, a tuple of two integers. These behave quite differently in many circumstances, such as when pattern matching. Be careful not to confuse them.

---

<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:** [April 24, 2018, 1:40pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/8 "2018-04-24T13:40:59Z")

</div>

This is a good start but I think your text is context-heavy for a beginner, the `many circumstances` would be really unclear for this audience. An alternative path might be

> Beware that the syntax for a constructor with multiple arguments
> 
> ```OCaml
> type t = A of float * float
> 
> ```
> 
> looks a lot like a tuple but this is not the case: all arguments are kept separated inside the constructor block, and it is not possible to extract those as a tuple without constructing a new tuple
> 
> ```OCaml
> let to_tuple (A (x,y)) = (x,y)
> let wrong_to_tuple (A x) = x
> 
> ```
> 
> If you want to pack all arguments together, it is possible to use a tuple as a constructor argument at the price of a bulkier memory representation:
> 
> ```OCaml
> type s = B of (float * float)
> let to_tuple_bis (B x) = x
> 
> ```

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [April 24, 2018, 2:21pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/9 "2018-04-24T14:21:46Z")

</div>

I find the beginning of what you wrote there very clear, i.e.:

> Beware that the syntax for a constructor with multiple arguments
> 
> ```auto
> type t = A of float * float
> 
> ```
> 
> looks a lot like a tuple but this is not the case:

but I think as a beginner I would have found the rest quite confusing. It discusses things like memory representation and tradeoffs on that which a beginner will not be prepared to think about, and brings in a couple of different **let** declaration styles as well.

How about:

> Beware! The syntax for a constructor with multiple arguments:
> 
> ```auto
> type t = A of float * float
> 
> ```
> 
> looks confusingly like it takes a tuple as its argument. However, `A` is a constructor that takes two `float` arguments. It is different from:
> 
> ```auto
> type t = B of (float * float)
> 
> ```
> 
> in which `B` is a constructor that takes one argument, a tuple of two `float`s.
> 
> The two will behave differently under pattern matching, as `A` has two arguments, and `B` has only one.

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [April 24, 2018, 2:28pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/10 "2018-04-24T14:28:33Z")

</div>

(It might be reasonable to _then_ show a difference in pattern matching between `A` and `B`.)

---

<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:** [April 24, 2018, 2:33pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/11 "2018-04-24T14:33:05Z")

</div>

Yes, the part about memory was too technical.  
I agree that an example would complement nicely your text:

> ```OCaml
> let a_to_tuple a = match a with
> | A (x,y) -> (x,y)
> let b_to_tuple b = match b with
> | B t -> t 
> 
> ```

Also, I would rename the second type to `s`, to avoid using type-directed disambiguation (which is now described in a subsection at the end of this section) at this stage.

At last, I think that in a tutorial, it is not fair to introduce a potential choice without either explaining the potential consequence of this choice or advising on a branch, so I would add:

> In doubt, it is generally more efficient to use the multiple arguments version.

Maybe with a reference to the C runtime chapter?

---

<div class="post-metadata">

**Author:** ![bobbypriambodo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bobbypriambodo/32/179_2.png) [@bobbypriambodo](https://discuss.ocaml.org/u/bobbypriambodo)\
**Post date:** [April 24, 2018, 4:00pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/12 "2018-04-24T16:00:38Z")

</div>

> [@n4323](#):
>
> I wonder what Reason does here?

Reason does the same (different syntax for each), but [specifically mentioned about it](https://reasonml.github.io/docs/en/variant.html#tips-tricks).

> **Be careful** not to confuse a constructor carrying 2 arguments with a constructor carrying a single tuple argument:
> 
> ```auto
> type account =
> | Facebook(string, int) /* 2 arguments */;
> type account2 =
> | Instagram((string, int)) /* 1 argument - happens to be a 2-tuple */;
> 
> ```

---

<div class="post-metadata">

**Author:** ![n4323](https://avatars.discourse-cdn.com/v4/letter/n/97f17d/32.png) [@n4323](https://discuss.ocaml.org/u/n4323)\
**Post date:** [April 24, 2018, 4:10pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/13 "2018-04-24T16:10:34Z")

</div>

Ok, but to construct the values, does it also allow the same syntax in both cases like OCaml syntax does?

I.e. is `let a = Facebook("", 0) and let a2 = Instagram("",0)` valid?

I find that aspect the most confusing.

---

<div class="post-metadata">

**Author:** ![n4323](https://avatars.discourse-cdn.com/v4/letter/n/97f17d/32.png) [@n4323](https://discuss.ocaml.org/u/n4323)\
**Post date:** [April 24, 2018, 4:14pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/14 "2018-04-24T16:14:46Z")

</div>

IMO the most confusing part is that

`let b_to_tuple b = match b with B (x, y) -> (x, y)`

is also valid.

---

<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:** [April 24, 2018, 4:31pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/15 "2018-04-24T16:31:54Z")

</div>

I see your point, but since `B t` is a valid pattern, it seems coherent that expanding `t` to `(x,y)` works.

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [April 24, 2018, 4:45pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/16 "2018-04-24T16:45:47Z")

</div>

> [@n4323](#):
>
> IMO the most confusing part is that
> 
> ```auto
> let b_to_tuple b = match b with B (x, y) -> (x, y)
> 
> ```
> 
> is also valid.

Yah. It might be important to note that but note the difference in what it means. Because the syntax is confusing, it would be best to err on the side of explicitness and clarity here.

---

<div class="post-metadata">

**Author:** ![n4323](https://avatars.discourse-cdn.com/v4/letter/n/97f17d/32.png) [@n4323](https://discuss.ocaml.org/u/n4323)\
**Post date:** [April 24, 2018, 5:10pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/17 "2018-04-24T17:10:13Z")

</div>

Yes. Maybe one could point out that `A t` does not work to make the difference clear? Not sure.

---

<div class="post-metadata">

**Author:** ![perry](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/perry/32/518_2.png) [@perry](https://discuss.ocaml.org/u/perry)\
**Post date:** [April 24, 2018, 5:56pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/18 "2018-04-24T17:56:40Z")

</div>

An example from the Mantis thread seems particularly appropriate.

> ```auto
> type t = A of int * string
> let x = (3, "haha")
> let y = A x (* This fails, because A needs two parameters. *)
> 
> ```

---

<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:** [April 24, 2018, 8:59pm UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/19 "2018-04-24T20:59:32Z")

</div>

That sounds like the right example to illustrate the difference.

---

<div class="post-metadata">

**Author:** ![n4323](https://avatars.discourse-cdn.com/v4/letter/n/97f17d/32.png) [@n4323](https://discuss.ocaml.org/u/n4323)\
**Post date:** [April 25, 2018, 8:42am UTC](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898/20 "2018-04-25T08:42:01Z")

</div>

> [@perry](#):
>
> type t = A of int \* string  
> let x = (3, “haha”)  
> let y = A x (\* This fails, because A needs two parameters. \*)

one could add

```ocaml
let y = A (3, "haha") (* This succeeds, because here (3, "haha") is parsed as two constructor arguments. *)

```

I think this is a wart in the language but fortunately not encountered so frequently.

[Next page](https://discuss.ocaml.org/t/sum-type-constructor-declaration-subtlety-and-documentation-wanted/1898.md?page=2)
