123456789101112131415161718192021222324252627282930313233343536373839404142434445moduleField(* field parsing *)=structtype'aresult=('a,string)Result.ttype'aparser=string->'aresultopenResult.Monad_infixletexn_validatefxmsg=tryOk(fx)with_->Errormsgletints=exn_validateInt.of_strings"Expected integer value"letpositive_ints=ints>>=funi->ifi>=0thenOkielseError"Expected positive integer value"letbounded_int~lo~his=ints>>=funi->ifi>=lo&&i<=hithenOkielseletmsg=Printf.sprintf"Expected integer value between %d and %d"lohiinErrormsgletstring_with_no_seps=ifString.containss'\n'||String.containss'\t'thenletmsg="Expected string without tab or newline character"inErrormsgelseOksletparse?(ctx="<unknown>")fs=matchfswith|Ok_asr->r|Errormsg->letmsg=Printf.sprintf"Field %s is incorrect: %s"ctxmsginErrormsgletparse_all?ctxfxs=parse?ctx(funxs->Result.all(List.mapxs~f))xsend