Ignacio Tiraboschi
Ignacio Tiraboschi

Reputation: 422

How can I define notation in OCaml?

I'm trying to define notation for a type I defined in my OCaml project. Basically this type allows me to express either one or two values of a type and I called it maybe_pair. I'd like to be able to write some notation for defining values of this type, for example:

I'm basically trying to imitate how the lists notation work, but I believe this may be impossible.

Upvotes: 1

Views: 201

Answers (3)

Kiran Gopinathan
Kiran Gopinathan

Reputation: 73

You can write a ppx-rewriter to partially achieve your goal, although the notation with angle brackes isn't supported.

I'll assume the pair is defined as follows:

(* file: pair.ml *)

type 'a maybe_pair = MkPair of 'a * 'a option [@@deriving show]

The ppx extension should then look as follows:

(* file: ppx_pair.ml *)

open Ppxlib

let name = "mp"

let expand ~loc ~path:_ expr =
  match expr with
  | {pexp_desc = Pexp_sequence (e1,e2); _} -> [%expr Pair.MkPair ([%e e1], Some [%e e2]) ]
  | e1 -> [%expr Pair.MkPair ([%e e1], None) ]



let ext =
  Extension.declare name Extension.Context.expression
    Ast_pattern.(single_expr_payload __)
    expand


let () = Driver.register_transformation name ~extensions:[ext]

We can see it in action as follows:

let () =
  let x = [%mp 1] in
  Format.printf "x is %a\n" (Pair.pp_maybe_pair Format.pp_print_int) x;
  let x = [%mp 1; 2] in    
  Format.printf "x is %a\n" (Pair.pp_maybe_pair Format.pp_print_int) x

Outputs:

x is (Pair.MkPair (1, None))
x is (Pair.MkPair (1, (Some 2)))

I've made a minimally working example project structure here: https://gitlab.com/gopiandcode/example-ppxlib

Upvotes: 0

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66803

You can't get the notation you want just by defining OCaml functions. You can define < and > as infix operators (with a fixed pre-defined precedence), but you can't define them to work in pairs like parentheses.

You can get any desired syntax using the OCaml syntax extension mechanism ppx. But this is a large subject, too big for an answer here on StackOverflow (in my opinion).

You can read about PPX here: https://ocamlverse.github.io/content/ppx.html

And here: https://github.com/ocaml-ppx/ppxlib

Upvotes: 1

Christian Lindig
Christian Lindig

Reputation: 1246

The type below can hold either one or two values of type 'a:

type 'a maybe_pair = Single of 'a | Double of 'a * 'a

Upvotes: 0

Related Questions