Supposing I have a record with several fields, and each field belongs to a basic type:
type person_info =
{ name : string;
surname : string;
nickname : string;
age : int;
...
};;
Now, I want to add some “meta data” and a few common functions like validation, so I can take an “invalidated record” and produce a valid one. My first simple approach was to use a tuple, where the value in the first position would be the actual field value, and the value in the second position would include all this “meta data”:
type 'a field_meta = {
id: int;
validate: 'a -> bool;}
type 'a field = ('a* 'a field_meta)
type person_info = {
name: string field;
age: int field;}
let name_meta = { id = 1; validate = (fun _ -> true) }
let age_meta = { id = 2; validate = (fun _ -> true) }
let record_a =
{
name = ("Joan", name_meta);
age = (22, age_meta)
}
let record_b =
{
name = ("Paul", name_meta);
age = (24, age_meta)
}
This allows to validate records quite comfortably:
let valid r =
[r.name |> validate; r.age |> validate] |>
(List.for_all (fun a -> a == true))
I guess one could replace the tuples with modules as well, to better encapsulate this “meta data” and remove boilerplate. I like the simplicity and power of tuples
What is bugging me now is that I can’t find a way so that I can create a list from the record field values, because each of them is of different type. let recList r = [r.name; r.age]
fails to compile. This is understandable, but it also means that for every new function in the spirit of validate
that has the shape “any field type in, one type out” I will have to manually walk through all the fields in the record. An example would be a size
function that returns an int
and apply it to all the fields to get the record size.
I imagine there must be a more modular way to do this. So my question is: is there some way in OCaml to abstract these shared behaviors between fields (functions like validate
and size
) so creating a list from the value of each field becomes possible? I’ve been reading a lot about different features and techniques in the language (GADTs, existential types, functors) but I couldn’t figure out a clear path to a solution.
Thanks!