Using a variant type constructor with just one tuple value

陌路散爱 提交于 2019-12-21 04:48:14

问题


# 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 is it that I must do Foo (1, 2) to avoid that error even t has the appropriate type?


回答1:


This is one of the troubling parts of OCaml syntax, in my opinion. Despite the way it looks, the constructor Foo doesn't require a 2-tuple as its argument. It requires, syntactically, two values in parentheses--but they aren't a tuple. So it's simply the case that t has the wrong type. The way to make this work is to say:

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

The problem really is that parentheses are being used for two different things (or so I claim). Once you get used to this it's not so difficult to deal with.

Edit: if you want the constructor Foo to take a single tuple, rather than two separate values, you can define it like this:

type foo = Foo of (int * int)

Then the rest of your original code will work.




回答2:


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

This is also the reason why, for example, algorithms that use association lists (for examples Hashtables with linked list buckets) sometimes define their own datatype 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 high-level case such specializations are not terribly important (and can hinder code reuse), but it's still nice to be able to get down to such technical details when you actually need tighter control over memory representation.



来源:https://stackoverflow.com/questions/9774671/using-a-variant-type-constructor-with-just-one-tuple-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!