Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

optics.ml

An experimental optics library for OCaml. See accessor library for a more comprehensive implementation.

Usage

% dune utop
# open Optics;;
# view _1 (42, 3.14);;
- : int = 42
# (42, (3.14, "foobar")) |> view (_2 // _1);;
- : float = 3.14
# (42, (3.14, "foobar")).%[_2 // _1];;
- : float = 3.14
# set _Some "foobar" (Some 42);;
- : string option = Option.Some "foobar"
# (42, (None, "foobar")).%[_2 // _1 // _Some] <- 0;;
- : int * (int option * string) = (42, (Option.None, "foobar"))
# (Some [1; 2; 3], 3.14) |> _1 // _Some // sets' List.map %~ succ;;
- : int list option * float = (Option.Some [2; 3; 4], 3.14)
# _Some // to_' List.length;;
- : (_[< `Affine_fold ], '_weak1 list option -> '_weak1 list option,
     int -> int)
    t
= <fun>
# view _Some;;
Error: This expression has type
         ([< prism ] as 'a, 'b option -> 'c option, 'b -> 'c) t =
           unit -> ('a, 'b option -> 'c option, 'b -> 'c) Optics._t
       but an expression was expected of type
         ([> getter ] as 'd, 'e -> 'f, 'g -> 'h) t =
           unit -> ('d, 'e -> 'f, 'g -> 'h) Optics._t
       Type
         ('a, 'b option -> 'c option, 'b -> 'c) Optics._t =
           ('a, 'b option, 'c option, 'b, 'c) Optics.__t
       is not compatible with type
         ('d, 'e -> 'f, 'g -> 'h) Optics._t = ('d, 'e, 'f, 'g, 'h) Optics.__t
       Type 'a = [< `Affine_fold | `Affine_traversal | `Prism | `Setter ]
       is not compatible with type 'd = [> `Affine_fold | `Getter ]
       The first variant type does not allow tag(s) `Getter

# #require "jsonaf";;
# let john =
  {|
{
  "firstName": "John",
  "lastName": "Smith",
  "isAlive": true,
  "age": 27
}
|}
  |> Jsonaf.parse
  |> Base.Or_error.ok_exn
;;
val john : Jsonaf_kernel.t =
  `Object
    [("firstName", `String "John"); ("lastName", `String "Smith");
     ("isAlive", `True); ("age", `Number "27")]
# john.%?[Json.(_Object // key "age" // _Int)];;
- : int option = Option.Some 27
# john.%?[Json.(_Object // key "isAlive" // _Bool)];;
- : bool option = Option.Some true
# john.%?[Json.(_Object // key "first-name" // _String)];;
- : Json.t option = Option.None
# john.%?[Json.(_Object // key "firstName" // _String)];;
- : string option = Option.Some "John"

Optics Hierarchy

classDiagram

class setter {
  + over
  + set
}

class affine_fold {
  + preview
  + previews
  + is
  + isn't
}

setter      <|-- affine_traversal
affine_fold <|-- affine_traversal
class affine_traversal {
  + matching
}

affine_fold <|-- getter
class getter {
  + get
  + view
  + views
}

affine_traversal <|-- prism

getter <|-- lens
affine_traversal <|-- lens

prism <|-- iso
lens <|-- iso
Loading

Optics and weak polymorphism

Due to the value restriction, optics created with function application has a weakly polymorphic type.

# sets List.map;;
- : (_[< setter ], '_weak2 list -> '_weak3 list, '_weak2 -> '_weak3) Optics._t
<abstr>

So, for example, if we want a polymorphic List.map setter, we need to wrap it in a thunk:

# let _List_map () = sets List.map;;
# _List_map;;
- : unit -> ([< setter ], 'a list -> 'b list, 'a -> 'b) Optics._t = <fun>

This library exports optics wrapped in a thunk (unit → _ Optics._t) as _ Optics.t and defines optics operations over them. There are some functions which directly create a _ Optics.t value, whose name is suffixed by '. If you want to create an _ Optics.t value inline, these funciton would be a handy choice.

# [1;2;3] |> set _List_map 1;;
- : int list = [1; 1; 1]
# [1;2;3] |> set (sets' List.map) 1;;
- : int list = [1; 1; 1]

NB: Optics composition (//) has no raw-optics-returning variants. So, if you want to bind a variable by optics composed with (//), you need to eta-expand it.

# let _1_2 () = () |> _1 // _2;;
# _1_2;;
- : unit -> ([< lens ], ('a * 'b) * 'c -> ('a * 'd) * 'c, 'b -> 'd) Optics._t =

About

an experimental optic library for OCaml

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages