Is it possible to have a parameter with multiple types in Ocaml?
I have defined two different types and both of those types have an address field:
type symbol =
{
address : string;
name : string;
}
type extern_symbol =
{
address : string;
name : string;
...
}
I also have a function which takes a symbol list as parameter and does checks with the address field. Now I'd like to reuse the code of the function for an extern_symbol list. The function would do exactly the same with the other list. Is there a way to get that done without having to write duplicate code?
You can't do this directly with record parameters, as all record types are distinct. There's no type for the notion of "any record with a field named address
of type string". Hence you can't have a parameter of that type.
You could, of course, just pass the address to the function instead of the whole record if that's all you need.
Or you could pass a function that extracts the address:
let myfun address_of r =
do_what_you_want (address_of r)
let internal_addr (r: symbol) = r.address
let external_addr (r: extern_symbol) = r.address
myfun internal_addr r1
myfun external_addr r2
So then myfun
has a type like this:
(a -> string) -> a -> result
This generalizes to other operations that can be applied to both record types.
You can also use object types rather than records. There is a type for the notion of "any object with a method named address
that returns a string":
< address : string; .. >
For example:
# let myfun2 ob = do_what_i_wanted ob#address;;
val myfun2 : < address : string; .. > -> string = <fun>
Finally, you could make the two types different variants of the same type:
type symbol =
| Internal of { address: string; name: string }
| External of { address: string; name: string; ... }
Then there would be no problem whatsoever handling them by the same function:
let myfun3 sym =
let addr =
match sym with
| Internal x -> x.address
| External x -> x.address
in
do_what_i_wanted addr