Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### Unreleased

- Add `Pidign.Pris` for bi-directional definition (by [mspwn](https://github.com/mspwn) and [xvw](https://github.com/xvw))

### v1.0.0

#### Pidgin
Expand Down
1 change: 1 addition & 0 deletions lib/pidgin.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
module Repr = Repr
module Kind = Kind
module Check = Check
module Prism = Prism
module Driver = Driver
module Sexp = Sexp
module Csexp = Csexp
Expand Down
6 changes: 4 additions & 2 deletions lib/pidgin.mli
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
to that of JSON) and to provide:

- a DSL for describing arbitrary data structures in this language
(see {!module:Repr})
(see {!module:Repr}).
- Validation functions that operate on data described using this
DSL (see {!module:Check})
DSL (see {!module:Check}).
- [Repr] and [Check] can be combined using {!module:Prism}.
- A bidirectional conversion approach (see {!module:Driver}),
imposing a cost due to the indirect nature of the generic format
(though it is viable in many scenarios).
Expand Down Expand Up @@ -48,4 +49,5 @@ module Csexp = Csexp

(** {1 Misc} *)

module Prism = Prism
module Misc = Misc
25 changes: 25 additions & 0 deletions lib/prism.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
(* Copyright (c) 2026, Cargocut and the Pidgin developers.
All rights reserved.

SPDX-License-Identifier: BSD-3-Clause *)

type 'a t =
{ conv : 'a Repr.conv
; check : 'a Check.t
}

let make ~conv ~check = { conv; check }
let conv { conv; _ } = conv
let check { check; _ } = check

let invmap f g { conv; check } =
{ check = (fun x -> x |> check |> Result.map f)
; conv = (fun x -> x |> g |> conv)
}
;;

let refine f g { conv; check } =
{ check = (fun x -> Result.bind (check x) f)
; conv = (fun x -> x |> g |> conv)
}
;;
38 changes: 38 additions & 0 deletions lib/prism.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
(* Copyright (c) 2026, Cargocut and the Pidgin developers.
All rights reserved.

SPDX-License-Identifier: BSD-3-Clause *)

(** A [Prism] is used to describe a codec that enables serialization
and deserialization (it consists of a {!type:Repr.conv} and a
{!type:Check.t} pair). *)

(** {1 Types} *)

(** The type that describes the pair of converter and validator. *)
type 'a t

(** {1 Building prisms} *)

(** [make ~conv ~check] constructs a prism for type ['a]. *)
val make : conv:'a Repr.conv -> check:'a Check.t -> 'a t

(** {1 Running prisms} *)

(** [conv prism] extract the prism conversion function. *)
val conv : 'a t -> 'a Repr.conv

(** [check prism] extract the prism validation function. *)
val check : 'a t -> 'a Check.t

(** {1 Helpers}

A few additional tools for working with prisms. *)

(** [invmap f g prism] map both [f] and [g] on, respectively, [check]
and [conv]. *)
val invmap : ('a -> 'b) -> ('b -> 'a) -> 'a t -> 'b t

(** [refine f g prism] bind [f] and map [g] on, respectively, [check]
and [conv]. *)
val refine : ('a, 'b) Check.fn -> ('b -> 'a) -> 'a t -> 'b t
Loading