Skip to content
master
Switch branches/tags
Code
This branch is 62 commits ahead of avsm:master.
Contribute

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
pkg
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Functional Lenses

Build Status

This package provides some basic types and functions for using lenses in OCaml. Functional lenses are based on F# implementation in FSharpX. See src/FSharpx.Extras/Lens.fs for the original implementation. Written by Alessandro Strada.

See also:

Examples

First load Lens in utop.

utop # #use "lens.ml";;

Given a couple of records

    type car = {
        make : string;
        model: string;
        mileage: int;
      };;

    type editor = {
        name: string;
        salary: int;
        car: car;
    };;

    type book = {
        name: string;
        author: string;
        editor: editor;
    };;

Create a new nested record

    let scifi_novel = {
       name =  "Metro 2033";
       author = "Dmitry Glukhovsky";
       editor =  {
         name = "Vitali Gubarev";
         salary =  1300;
         car =  {
           make = "Lada";
           model = "VAZ-2103";
           mileage = 310000
        }
      }
    };;

Now to construct a few lenses to access some things

    let car_lens = {
        get = (fun x -> x.car);
        set = (fun v x -> { x with car = v })
      };;

    let editor_lens = {
        get = (fun x -> x.editor);
        set = (fun v x -> { x with editor = v })
    };;

    let mileage_lens = {
        get = (fun x -> x.mileage);
        set = (fun v x -> { x with mileage = v })

    };;

Using these lenses we can modify the mileage without having to unpack the record

    let a = compose mileage_lens (compose car_lens editor_lens) in
    _set 10 scifi_novel a;;

Or using the Infix module we can do the same thing, only shorter.

    _set 10 scifi_novel (editor_lens |-- car_lens |-- mileage_lens);;

    (* or *)

    ((editor_lens |-- car_lens |-- mileage_lens) ^= 10) @@ scifi_novel;;

Ppx syntax extension

Lenses can be generated using the 'lens.ppx_deriving' plugin for ppx_deriving

#require "lens.ppx_deriving";;

type car = {
  make : string;
  model: string;
  mileage: int;
} [@@deriving lens];;

val car_make: (car, string) Lens.t
val car_model: (car, string) Lens.t
val car_mileage: (car, int) Lens.t

The prefix option can be used to prefix each lens name with lens.

#require "lens.ppx_deriving";;

type car = {
  make : string;
  model: string;
  mileage: int;
} [@@deriving lens { prefix = true }];;

val lens_car_make: (car, string) Lens.t
val lens_car_model: (car, string) Lens.t
val lens_car_mileage: (car, int) Lens.t

The submodule option groups all the lenses in a sub-module Lens.

#require "lens.ppx_deriving";;

type car = {
  make : string;
  model: string;
  mileage: int;
} [@@deriving lens { submodule = true }];;

module Lens :
  val make : (car, string) Lens.t
  val model : (car, string) Lens.t
  val mileage : (car, int) Lens.t
end

When the prefix and submodule options are combined, this is the module name which is prefixed.

#require "lens.ppx_deriving";;

type car = {
  make : string;
  model: string;
  mileage: int;
} [@@deriving lens { submodule = true; prefix = true }];;

module CarLens :
  val make : (car, string) Lens.t
  val model : (car, string) Lens.t
  val mileage : (car, int) Lens.t
end

About

Private extraction of astrada's lens library

Resources

Packages

No packages published