Skip to content

cargocut/pidgin

Repository files navigation

Warning

This project is still highly experimental, but we would be delighted to receive feedback (but please be careful with production).

pidgin

Pidgin is a generic key-value data structure description language that enables fine-grained validation to deal with format like JSON, S-expression, Yaml, ToML etc. This makes it possible to derive generic pretty-printers, equality functions, and serialization/deserialization functions.

The main idea is to present a minimal representation (very similar to that of JSON) and to provide:

  • A DSL for describing arbitrary data structures in this language.
  • Validation functions that operate on data described using this DSL
  • A bidirectional conversion approach, imposing a cost due to the indirect nature of the generic format (though it is viable in many scenarios).

Pidgin does not statically preserve the type of expressions; instead, it hides them, which allows expressions written in this language to be treated as an untyped runtime representation of arbitrary OCaml values (enabling the derivation of pretty-printers and equality functions, for example).

History and Trivia

Pidgin is derived from the Yocaml.Data module (from the YOCaml project) and the Rensai validation model, which originated from Kohai.

The name "Pidgin", a grammatically simplified form of contact language that develops between two or more groups of people that do not have a language in common (Wikipedia), was suggested by Lorie Den Os.

A simple example

Here is a very short example that demonstrates how to serialize and deserialize Pidgin expressions:

module Gender = struct
  type t =
    | Male
    | Female
    | Other of string

  let to_pidgin x =
    Repr.string
      (match x with
       | Other s -> s
       | Male -> "male"
       | Female -> "female")
  ;;

  let from_pidgin =
    let open Check in
    string
    $ function
    | "male" | "m" -> Male
    | "female" | "f" -> Female
    | other -> Other other
  ;;
end
module Human = struct
  type t =
    { nickname : string
    ; firstname : string option
    ; lastname : string option
    ; age : int option
    ; gender : Gender.t
    }

  let make ?firstname ?lastname ?age ~nickname ~gender () =
    { nickname; firstname; lastname; age; gender }
  ;;

  let to_pidgin { nickname; firstname; lastname; age; gender } =
    let open Repr in
    record
      [ "nickname", string nickname
      ; "firstname", option string firstname
      ; "lastname", option string lastname
      ; "age", option int age
      ; "gender", Gender.to_pidgin gender
      ]
  ;;

  let from_pidgin =
    let open Check in
    record (fun fields ->
      let+ nickname = req ~alt:[ "nick"; "pseudo" ] fields "nickname" string
      and+ gender = req fields "gender" Gender.from_pidgin
      and+ firstname = opt ~alt:[ "first_name" ] fields "firstname" string
      and+ lastname = opt ~alt:[ "last_name"; "name" ] fields "lastname" string
      and+ age = opt fields "age" int in
      make ?firstname ?lastname ?age ~nickname ~gender ())
  ;;
end

About

Pidgin is a common language for describing and validating complex data structures

Resources

License

Stars

11 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors