From 554708006485cd3b5b4d0c417570cbf089c7b61a Mon Sep 17 00:00:00 2001 From: Cuihtlauac ALVARADO Date: Tue, 23 Apr 2024 17:19:57 +0200 Subject: [PATCH] Deserialise and post-process recipes --- .../cookbook/deserialise-from-yaml/00-yaml.ml | 10 +-- .../deserialise-from-yaml/01-hl_yaml.ml | 10 +-- .../00-yaml.ml | 72 ++++++++++++++++++ .../01-hl_yaml.ml | 73 +++++++++++++++++++ data/cookbook/get-todays-date/00-stdlib.ml | 10 ++- data/cookbook/read-text-file/00-in_channel.ml | 8 +- 6 files changed, 163 insertions(+), 20 deletions(-) create mode 100644 data/cookbook/deserialise-post-process-from-yaml/00-yaml.ml create mode 100644 data/cookbook/deserialise-post-process-from-yaml/01-hl_yaml.ml diff --git a/data/cookbook/deserialise-from-yaml/00-yaml.ml b/data/cookbook/deserialise-from-yaml/00-yaml.ml index 74f2fa5dff..302ade930f 100644 --- a/data/cookbook/deserialise-from-yaml/00-yaml.ml +++ b/data/cookbook/deserialise-from-yaml/00-yaml.ml @@ -9,7 +9,7 @@ packages: used_libraries: - ppx_deriving_yaml --- -(* This is the string we are deserializing into the types we define below. *) +(* The syntax `{| ... |}` is a quoted string. *) let yaml = {| french name: pâte sucrée ingredients: @@ -30,16 +30,16 @@ steps: - add flour |} -(* The `[@@deriving of_yaml]` attribute makes makes the ppx from the library `ppx_deriving_yaml` - generate the function ``ingredient_of_yaml : Yaml.value -> (ingredient, [> `Msg of string]) result`` +(* The `[@@deriving of_yaml]` attribute makes library `ppx_deriving_yaml` generate the function + ``ingredient_of_yaml : Yaml.value -> (ingredient, [> `Msg of string]) result`` If both serialising and deserialising are needed, replace `of_yaml` by `yaml`. *) type ingredient = { name: string; weight: int; } [@@deriving of_yaml] -(* The function ``recipe_of_yaml : Yaml.value -> (ingredient, [> `Msg of string]) result`` - generated here internally uses `ingredient_of_yaml`. *) +(* The `[@@deriving of_yaml]` attribute makes library `ppx_deriving_yaml` generate the function + ``recipe_of_yaml : Yaml.value -> (ingredient, [> `Msg of string]) result``. *) type recipe = { name: string; [@key "french name"] ingredients: ingredient list; diff --git a/data/cookbook/deserialise-from-yaml/01-hl_yaml.ml b/data/cookbook/deserialise-from-yaml/01-hl_yaml.ml index 6667f7a2ab..37016a5c88 100644 --- a/data/cookbook/deserialise-from-yaml/01-hl_yaml.ml +++ b/data/cookbook/deserialise-from-yaml/01-hl_yaml.ml @@ -9,7 +9,7 @@ packages: used_libraries: - ppx_deriving_yojson --- -(* This is the string we are deserializing into the types we define below. *) +(* The syntax `{| ... |}` is a quoted string. *) let yaml = {| french name: pâte sucrée ingredients: @@ -30,7 +30,7 @@ steps: - add flour |} -(* The `[@@deriving of_yojson]` attribute makes the ppx from the library `ppx_deriving_yojson` generate the function +(* The `[@@deriving of_yojson]` attribute makes library `ppx_deriving_yojson` generate the function `ingredient_of_yojson : Yojson.Safe.t -> (ingredient, string) result`. If both serialising and deserialising are needed, replace `of_yojson` by `yojson`. *) type ingredient = { @@ -38,15 +38,15 @@ type ingredient = { weight: int; } [@@deriving of_yojson] -(* The function ``recipe_of_yojson : Yojson.Safe.t -> (ingredient, string) result`` generated here internally uses - `ingredient_of_yojson`. *) +(* The `[@@deriving of_yojson]` attribute makes library `ppx_deriving_yojson` generate the function + ``recipe_of_yojson : Yojson.Safe.t -> (ingredient, string) result``. *) type recipe = { name: string; [@key "french name"] ingredients: ingredient list; steps: string list; } [@@deriving of_yojson] -(* `parse` takes a function that converts from `Yojson.Safe.t` into the desired record type as an argument. *) +(* Parsing receives conversion into record as an argument. *) let pate_sucree = yaml |> Hl_yaml.Unix.parse ~of_yojson:recipe_of_yojson diff --git a/data/cookbook/deserialise-post-process-from-yaml/00-yaml.ml b/data/cookbook/deserialise-post-process-from-yaml/00-yaml.ml new file mode 100644 index 0000000000..b0db02c325 --- /dev/null +++ b/data/cookbook/deserialise-post-process-from-yaml/00-yaml.ml @@ -0,0 +1,72 @@ +--- +packages: +- name: yaml + tested_version: 3.2.0 + used_libraries: + - yaml +- name: ppx_deriving_yaml + tested_version: 0.2.2 + used_libraries: + - ppx_deriving_yaml +--- +(* The syntax `{| ... |}` is a quoted string. *) +let yaml = {| +french name: pâte sucrée +ingredients: +- flour: 250 +- butter: 100 +- sugar: 100 +- egg: 50 +- salt: 5 +steps: +- soften butter +- add sugar +- add egg and salt +- add flour +|} + +(* The `[@@deriving of_yaml]` attribute makes library `ppx_deriving_yaml` generate the function + ``ingredient_of_yaml : Yaml.value -> (ingredient, [> `Msg of string]) result`` + If both serialising and deserialising are needed, replace `of_yaml` by `yaml`. *) +type ingredient = { + name: string; + weight: int; +} [@@deriving of_yaml] + +(* The `[@@deriving of_yaml]` attribute makes library `ppx_deriving_yaml` generate the function + ``recipe_of_yaml : Yaml.value -> (ingredient, [> `Msg of string]) result``. *) +type recipe = { + name: string; [@key "french name"] + ingredients: ingredient list; + steps: string list; +} [@@deriving of_yaml] + +(* Post-processing is needed before using `recipe_of_yaml`. + This what function `add_keys` and `at_ingredients` do. *) +let add_keys : Yaml.value -> Yaml.value = function + | `O [(name, `Float weight)] -> + `O [ + ("name", `String name); + ("weight", `Float weight); + ] + | v -> v + +let at_ingredients f : Yaml.value -> Yaml.value = function + | `O [ + ("french name", `String name); + ("ingredients", `A ingredients); + ("steps", `A steps) + ] -> `O [ + ("french name", `String name); + ("ingredients", Yaml.Util.map_exn f (`A ingredients)); + ("steps", `A steps); + ] + | v -> v + +(* Parsing, post-processing and conversion into recordd are chained. *) +let pate_sucree = + yaml + |> Yaml.of_string + |> Result.map (at_ingredients add_keys) + |> fun yaml -> Result.bind yaml recipe_of_yaml + diff --git a/data/cookbook/deserialise-post-process-from-yaml/01-hl_yaml.ml b/data/cookbook/deserialise-post-process-from-yaml/01-hl_yaml.ml new file mode 100644 index 0000000000..8861144312 --- /dev/null +++ b/data/cookbook/deserialise-post-process-from-yaml/01-hl_yaml.ml @@ -0,0 +1,73 @@ +--- +packages: +- name: hl_yaml + tested_version: 1.0.0 + used_libraries: + - hl_yaml +- name: ppx_deriving_yojson + tested_version: 3.7.0 + used_libraries: + - ppx_deriving_yojson +--- +(* The syntax `{| ... |}` is a quoted string. *) +let yaml = {| +french name: pâte sucrée +ingredients: +- flour: 250 +- butter: 100 +- sugar: 100 +- egg: 50 +- salt: 5 +steps: +- soften butter +- add sugar +- add egg and salt +- add flour +|} + +(* The `[@@deriving of_yojson]` attribute makes library `ppx_deriving_yojson` generate the function + `ingredient_of_yojson : Yojson.Safe.t -> (ingredient, string) result`. + If both serialising and deserialising are needed, replace `of_yojson` by `yojson`. *) +type ingredient = { + name: string; + weight: int; +} [@@deriving of_yojson] + +(* The `[@@deriving of_yojson]` attribute makes library `ppx_deriving_yojson` generate the function + ``recipe_of_yojson : Yojson.Safe.t -> (ingredient, string) result``. *) +type recipe = { + name: string; [@key "french name"] + ingredients: ingredient list; + steps: string list; +} [@@deriving of_yojson] + +(* Post-processing is needed before using `recipe_of_yojson`. + This what function `add_keys` and `at_ingredients` do. *) +let add_keys : Yojson.Safe.t -> Yojson.Safe.t = function + | `Assoc [(name, `Int weight)] -> + `Assoc [ + ("name", `String name); + ("weight", `Int weight); + ] + | v -> v + +let at_ingredients f : Yojson.Safe.t -> Yojson.Safe.t = function + | `Assoc [ + ("french name", `String name); + ("ingredients", `List ingredients); + ("steps", `List steps) + ] -> `Assoc [ + ("french name", `String name); + ("ingredients", Yojson.Safe.Util.map f (`List ingredients)); + ("steps", `List steps); + ] + | v -> v + +(* Parsing receives post-processing and conversion into record as an argument. *) +let pate_sucree = + let of_yojson json = + json + |> at_ingredients add_keys + |> recipe_of_yojson in + yaml + |> Hl_yaml.Unix.parse ~of_yojson diff --git a/data/cookbook/get-todays-date/00-stdlib.ml b/data/cookbook/get-todays-date/00-stdlib.ml index 127383f270..53b4806549 100644 --- a/data/cookbook/get-todays-date/00-stdlib.ml +++ b/data/cookbook/get-todays-date/00-stdlib.ml @@ -6,16 +6,18 @@ discussion: | - **Alternative Libraries:** For more complex date-time operations, consider using external libraries like `calendar` or `timedesc`, which offer more functionalities like time zone handling and date arithmetic. --- -(* The `unix` library, which ships with OCaml's standard library, - provides functions to work with dates and times. *) +(* Use the `unix` library, which ships with OCaml's standard library, and + provides functions to work with dates and times. You can use the `Unix` module + to get the current date and time: *) let today = Unix.localtime (Unix.time ());; let day = today.Unix.tm_mday;; -(* Months are numbered 0 to 11. *) +(* Months are 0 to 11. *) let month = today.Unix.tm_mon + 1;; -(* Years are counted starting from 1900. *) +(* Years since 1900. *) let year = today.Unix.tm_year + 1900;; +(* You can use the `Printf` module to print the date: *) Printf.printf "The current date is %04d-%02d-%02d\n" year month day;; diff --git a/data/cookbook/read-text-file/00-in_channel.ml b/data/cookbook/read-text-file/00-in_channel.ml index de0d6d1967..80cad2b889 100644 --- a/data/cookbook/read-text-file/00-in_channel.ml +++ b/data/cookbook/read-text-file/00-in_channel.ml @@ -1,9 +1,5 @@ --- packages: [] --- -(* `with_open_text` opens a channel the file at the given path. - `input_all` reads all data from the input channel. - These functions can raise `Sys_error` exceptions. - *) -let text = - In_channel.(with_open_text "/etc/passwd" input_all) +(* Read the text file. *) +let text = In_channel.(with_open_text "/etc/passwd" input_all)