package ppx_lun

  1. Overview
  2. Docs
Optics with lun package and PPX

Install

Dune Dependency

Authors

Maintainers

Sources

lun-0.0.1.tbz
sha256=cca8badff83b470fdcfb1840116f8e8a6f2cb86cde2f44ed28cf26cbf692a793
sha512=fdded797a6a89f2900a9a2676ad096dd6e5a37833d7a30702e55276f5e01f62da190df0385e721abd0619e3461902b007074e3c92b4283c8f9e325f6f6fb8e17

Description

Tags

ppx optics

Published: 29 May 2023

README

Lun(ette), optics in OCaml

This small library proposes values (optics) allowing to access (and modify) fields of a record or to project values (or modify them) of a constructor in OCaml. These values can be composed together and thus facilitate the access and modification of certain fields in nested records.

As an example, here is a "nested" record c:

type a =
  { v : string }
type b =
  { a : a }
type c =
  { b : b
  ; c : float }

It can be annoying to update a from c:

let update_v : c -> string -> c = fun c v ->
  { c with b= { c.b with a= { v }}}

Lun(ette) thus proposes values which are called "optics" allowing to refer to the field of a record. The particularity of these values is that they can be composed between them:

let a_v () = Lun.lense (fun { v } -> v) (fun _ v -> { v })
let b_a () = Lun.lense (fun { a } -> a) (fun _ a -> { a })
let c_b () = Lun.lense (fun { b; _ } -> b) (fun c b -> { c with b })

let update_v c v =
  Lun.(set (c_b >> b_a >> a_v)) v c

ppx_lun

As you can see, the creation of these optics is quite simple. That's why Lun(ette) also offers a ppx that generates these values for you:

type a =
  { v : string } [@@deriving lun]
type b =
  { a : a } [@@deriving lun]
type c =
  { b : b
  ; c : float } [@@deriving lun]

let update_v c v =
  Lun.(set (c_b >> b_a >> a_v)) v c

The user can then use this ppx in his/her library or in his/her executable by adding this new field if he/she is a dune user:

+ (preprocess
+  (pps ppx_lun))

The user can also obtain the generated code directly from the tool provided in our distribution:

$ cat >main.ml <<EOF
type t = { v : int } [@@deriving lun]
EOF
$ lun main.ml
type t = {
  v: int }[@@deriving lun]
include
  struct
    let _ = fun (_ : t) -> ()
    let t_v () =
      Lun.lense (fun vObwn1M -> vObwn1M.v) (fun _ -> fun v -> { v })
    let _ = t_v
  end[@@ocaml.doc "@inline"][@@merlin.hide ]

How to us it?

Lun(ette) can be used for records but also for ADTs. We offer a fairly complete documentation on the use of this library (with examples) as well as a description of the use of ppx.

Dependencies (4)

  1. ppxlib >= "0.25.0"
  2. lun = version
  3. dune >= "3.5"
  4. ocaml >= "4.12.0"

Dev Dependencies (1)

  1. fmt with-test

Used by

None

Conflicts

None