import is a syntax extension that allows to pull in types or signatures from other compiled interface files.
Sponsored by Evil Martians.
import can be installed via OPAM:
$ opam install ppx_import
In order to use import, require the package ppx_import
.
For example:
# type loc = [%import: Location.t];;
type loc = Location.t = { loc_start : Lexing.position; loc_end : Lexing.position; loc_ghost : bool; }
# module type Hashable = [%import: (module Hashtbl.HashedType)];;
module type Hashable = sig type t val equal : t -> t -> bool val hash : t -> int end
It is also possible to import items from your own .mli file.
It's possible to combine import and deriving to derive functions for types that you do not own, e.g.:
type longident = [%import: Longident.t] [@@deriving show]
let () =
print_endline (show_longident (Longident.parse "Foo.Bar.baz"))
(* Longident.Ldot (Longident.Ldot (Longident.Lident ("Foo"), "Bar"), "baz") *)
Note that you need to require import before any deriving plugins, as otherwise deriving will not be able to observe the complete type.
It is possible to syntactically replace a type with another while importing a definition. This can be used to import only a few types from a group, or to attach attributes to selected referenced types.
For example, this snippet imports a single type from Parsetree and specifies a custom pretty-printer for deriving show.
type package_type =
[%import: Parsetree.package_type
[@with core_type := Parsetree.core_type [@printer Pprintast.core_type];
Asttypes.loc := Asttypes.loc [@polyprinter fun pp fmt x -> pp fmt x.Asttypes.txt];
Longident.t := Longident.t [@printer pp_longident]]]
[@@deriving show]
For module types, the replacements are specified using the standard with
construct. However, the replacement is still syntactic.
If you have a use case in mind that ppx_import does not cover (in particular, object-oriented features are not implemented), please open an issue.
import is distributed under the terms of MIT license.