Record validations

I will need to validate records before storing them in a database. Does something exist already to do that? (I didn’t find anything)

My current preference is to keep the record type as is, and apply a validation to it (contrary to this).

If I need to develop it myself, I’m looking for advice on how to structure my code. Here are the ideas to come to mind:

  • define a record with similar field names but the types of the fields would be ('a -> bool) list while the data record filed would be of type 'a. Validation would be checking that all functions return true for each field. Downside is that it requires an additional type for each record, and I’m not sure if traversing record fields is easy.
  • define a list of tuples (fieldname:string) * ( ('a->bool) list). One type is defined for validation of all records. But will be manipulating a tuple list easy for error extraction?

Maybe a bool returning function is not fine to get error messages, and the validation function should return a Result<bool,string>?
Would anonymous record be handy regarding the first idea?

Thanks in advance for your ideas

This might be a bit overkill for what you are trying to do, but maybe you can take some inspiration from it.

I recently wanted to run validation checks on a full data structure parsed from JSON files. I ended up writing something that almost looked like a unit test framework, but more geared towards verifying the data. I used the excellent Unquote library to define the requirements, and a ‘test runner’ that tested these quotations and returned a Result<unit, string> (so the Ok case has no data attached, the Error case contains a descriptive error message). You can take a look at the code here on GitHub. Lines 34-122 define the actual verification checks, the code before is the data structure for the tree of checks, line 124 and onwards actually runs the checks and builds a nicely formatted error message (example).

As I said, this is probably way overkill for your use case, but maybe there’s a pattern in there that you can use.

1 Like

I would not define new type for this. And definitely not string dictionaries. Just define functions. On type R = {X:A; Y:B} you can define a validateX:A->Result<unit, string> and validateY and combine them into a validate:R->Result<unit,string>.

Or you can define validateX:'A->Result<R, string> and validateY similarly and then `validate:R->unit = r |> Result.bind validateX |> Result.bind validateY |> Result.bind ignore. As in

Thanks for the reactions, I’ll probably go for the function approach.