Using a variant type constructor with a single tuple value

# type foo = Foo of int * int # let t = (1, 2) # Foo t Error: The constructor Foo expects 2 argument(s), but is applied here to 1 argument(s) 

How should I do Foo (1, 2) to avoid this error, even t is of the appropriate type?

+6
source share
2 answers

This is one of the problematic parts of OCaml syntax, in my opinion. Despite the way it looks, the Foo constructor does not require a 2-tuple as an argument. This requires syntactically two values ​​in parentheses, but they are not tuples. So this is just the case when t is of the wrong type. The way to do this work is to say:

 let (a, b) = t in Foo (a, b) 

The problem is that parentheses are used for two different things (or, as I say). Once you get used to it, it's not that hard to handle.

Edit : if you want the Foo constructor to take one tuple rather than two separate values, you can define it as follows:

 type foo = Foo of (int * int) 

Then the rest of your source code will work.

+10
source

Note that the difference between Foo of (a * b) and Foo of a * b exists for efficiency reasons: Foo of (a * b) has an argument, which is a tuple, a pointer to two elements on the heap. Foo of a * b has two arguments that are directly packaged with a tag, avoiding indirection.

This is also the reason that, for example, algorithms using association lists (e.g. Hashtables with associated buckets) sometimes define their own data type instead of reusing ('a * 'b) list :

 type ('a, 'b) assoc_list = | Nil | Cons of 'a * 'b * ('a, 'b) assoc_list 

Of course, in the general case at a high level, such specializations are not very important (and can prevent code reuse), but it’s nice to be able to go to such technical details when you really need more tight control over the memory representation.

+4
source

Source: https://habr.com/ru/post/911119/


All Articles