Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using open unions outside the module they were defined in

Why does this work fine?

module Account = struct

 type account_type = Current of float | Savings of float

end

let sarah = Account.Current 100.0;;

While the final line in the following produces an Error: syntax error?

module Account = struct

  type 'a account_type = [> `Current of float | `Savings of float ] as 'a

end

let pete = Account.`Current 100.0;;

That is, why can't I use the open union type outside the module without opening the module? I should say I've found out that changing the final line to:

open Account;;
let pete = `Current 100.0;;

works fine, but obviously this is cumbersome if I use account_type a lot, or alternatively I have to open Account at the start of any code section where account_type is used, which means I'd sacrifice the abstraction I'd get by using a signature for Account
I've trawled through several OCaml tutorials as well as the INRIA documentation, and I can't find any mention of how you do this.
Is it possible to avoid having to open the module every time I want to use an account_type?

Thanks in advance,

Zach

like image 592
ZJanes Avatar asked Oct 27 '11 15:10

ZJanes


2 Answers

In the second example, you actually don't have to open Account at all, the syntax is just `Current 100.0. A Polymorphic variant tag does not participate in any particular type. The type of `Current is [> `Current ], this (the >) means the type is at least `Current, and since that is a subset of the type accepted by the function, it will compile just fine. You can pass that same value to a number of functions that accept a polymorphic variant of the same name. Of course, there is a lack of static type information, and typing errors and situations can become quite complex.

Code Reuse through polymorphic variants talks about some advantages and use cases for them.

like image 200
nlucaroni Avatar answered Nov 15 '22 09:11

nlucaroni


The polymorphic variant constants like `Current are globally defined, similarly to integer constants. You wouldn't say Account.10 to reference the integer 10 inside the Account module.

This is the strength (and weakness) of polymorphic variants, you can use them without defining them (like you don't have to define 10 before using it).

So, as nlucaroni says, you don't have to open the Account module to get access to `Current.

Unlike the integers, polymorphic variants can also take parameters (as in your `Current 100.0). But the number of parameters and their types aren't fixed, and they can even vary for the same constructor in different places in the code. Hence the complexities also mentioned by nlucaroni.

[Formatting note: to get single backquotes ` to show up in typewriter-styled text, the markdown convention is to use doubled backquotes to enclose the text. This leaves single backquotes alone inside the text. Or at least it's working for me.]

like image 37
Jeffrey Scofield Avatar answered Nov 15 '22 10:11

Jeffrey Scofield