I'm trying to pretty print a custom record type that contains a Hashtable (using the Base standard library) in OCaml with ppx-deriving, but I need to implement Hashtbl.pp for it to work.
I've tried looking at examples online and the best one that I found is https://github.com/ocaml-ppx/ppx_deriving#testing-plugins, but I'm still getting strange type errors like "This function has type Formatter.t -> (string, Value.t) Base.Hashtbl.t -> unit. It is applied to too many arguments; maybe you forgot a `;'"
How do you extend the Hashtbl module with a pp function?
Here is my code so far (Value.t is a custom type which I successfully annotated with [##deriving show]:
open Base
(* Extend Hashtbl with a custom pretty-printer *)
module Hashtbl = struct
include Hashtbl
let rec (pp : Formatter.t -> (string, Value.t) Hashtbl.t -> Ppx_deriving_runtime.unit) =
fun fmt -> function
| ht ->
List.iter
~f:(fun (str, value) ->
Caml.Format.fprintf fmt "#[<1>%s: %s#]#." str (Value.string_of value))
(Hashtbl.to_alist ht)
and show : (string, Value.t) Hashtbl.t -> Ppx_deriving_runtime.string =
fun s -> Caml.Format.asprintf "%a" pp s
;;
end
type t =
{ values : (string, Value.t) Hashtbl.t
; enclosing : t option
}
[##deriving show]
Solution 1
The type of the values field of your record is a parametrized with two type variables, therefore the deriver is trying to use a general pp function that is parametrized by the key and data pretty-printers, e.g., the following will enable show for any hashtable (with any key and any value, as long as keys and values are showable,
module Hashtbl = struct
include Base.Hashtbl
let pp pp_key pp_value ppf values =
Hashtbl.iteri values ~f:(fun ~key ~data ->
Format.fprintf ppf "#[<1>%a: %a#]#." pp_key key pp_value data)
end
so you can finally define your type
type t = {
values : (string,Value.t) Hashtbl.t;
enclosing : t option;
} [##deriving show]
Solution 2 (recommended)
However, I would suggest another approach that instead of creating a general Hashtable module, creates a specialized Values module, e.g.,
module Values = struct
type t = (string, Value.t) Hashtbl.t
let pp ppf values =
Hashtbl.iteri values ~f:(fun ~key ~data ->
Format.fprintf ppf "#[<1>%s: %s#]#." key (Value.to_string data))
end
Now you can use it as,
type t = {
values : Values.t;
enclosing : t option;
} [##deriving show]
Solution 3
If you still want a generic printable hash table, then I would advise against using the include statement, but, instead, implement just the required printable interface for the ('k,'s) Hashtbl.t type, e.g.,
module Hashtbl_printable = struct
type ('k,'s) t = ('k, 's) Hashtbl.t
let pp pp_key pp_value ppf values =
Hashtbl.iteri values ~f:(fun ~key ~data ->
Format.fprintf ppf "#[<1>%a: %a#]#." pp_key key pp_value data)
end
type t = {
values : (string, Value.t) Hashtbl_printable.t;
enclosing : t option;
} [##deriving show]
Related
I would like to constrain a type variable to allow only polymorphic variant types, such that I could use the variable to construct other polymorphic variant types in a signature:
type 'a t
val f : 'a t -> [`Tag | 'a] t
Is there a way to accomplish this in OCaml? Perhaps using classes/objects instead? A naive attempt failed to compile:
type 'a t = { dummy: int } constraint 'a = [>]
let f : 'a t -> ['a | `Tag] t = fun _ -> { dummy = 0 }
^^
The type [> ] does not expand to a polymorphic variant type
Reason for the question:
I want to use the type signature to reflect capabilities of a t statically, to enforce that a t without a given capability can never be used inappropriately.
val do_something_cool : [<`Super_power] t -> unit
val do_something_else : [<`Super_power|`Extra_super_power] t -> unit
val enhance : 'a t -> ['a | `Super_power] t
val plain_t : [`Empty] t
let () = plain_t |> do_something_cool (* fails *)
let () = plain_t |> enhance |> do_something_cool (* succeeds *)
let () = plain_t |> enhance |> do_something_else (* succeeds *)
Obviously there are other ways to achieve this compile-time safety. For example, enhance could just return a [`Super_power] t that could be used in place of plain_t where required. However, I'm really curious whether the first way could succeed. I am writing a DSL which would be a lot more concise if all the capabilities of t could be reflected in its type.
The short answer is no: it is only possible to inline type declarations, not type variables. In other words, this is fine:
type on = [`On]
type off = [`Off]
type any = [ on | off ]
let f: [< any ] -> _ = fun _ -> ()
but not this
let merge: 'a -> 'b -> [ 'a | 'b ] = ...
However, if you only have a closed set of independent capabilities, it might work to switch to an object phantom type where each capacity correspond to a field and each field can be either on or off. For instance,
type +'a t constraint 'a = < super: [< any ]; extra: [< any ]>
Then consumer functions that only require a conjunction of capabilities are relatively easy to write:
val do_something_cool : < super:on; ..> t -> unit
val do_something_extra : < extra:on; ..> t -> unit
val do_something_super_but_not_extra: <super:on; extra:off; .. > t -> unit
but switching a capability on or off is more complex and fixes the set of capabilities:
val enhance : < super: _; extra: 'es > t -> < super: on; extra:'es > t
Beyond those limitations, everything works as expected. For instance, if I have a variable x
val x: <super: off; extra:on > t
This works:
let () = do_something_extra x
whereas
let () = do_something_cool x
fails and finally
let () =
let x = enhance x in
do_something_cool x; do_something_extra x
works fine too.
The main issue is thus writing the enable function. One trick that may help is to
write helper type to manipulate more easily a subset of capabilities.
For instance, if I have a complex type:
type 'a s
constraint 'a = < a: [< any]; b:[< any]; c: [< any ]; d: [< any] >
I can use the following type:
type ('a, 'others) a = < a:'a; b:'b; c:'c; d: 'd>
constraint 'others = 'b * 'c * 'd
to select the capability a, and thus write
val enable_a: (_,'rest) a s -> (on, 'rest) a s
without having to explicit the three type variables hidden in 'rest.
I want to print a list with different element in it (for educational purpose)
I have read a tutorial that explain how to store different type in list.
type _ list =
[] : unit list
| ( :: ) : 'b * 'a list -> ('b ->'a) list;;
1 :: "e" :: 'r' :: [];; (* this is allowed *)
how I can do something like this pseudo-code:
match typeof(my_expr) with
int -> print_int
| string -> print_string
we will have "1,e,r" printed.
Some solutions i have searched
Change my type in text and printing it
Use a different type definition maybe ('a, 'b) list ?
I ask this because the OCaml toplevel know the type of every variable and show always the type in the right format: can I call this printer ?
Is there a solution only for toplevel that we can install with the #install_printer ?
I know that compiler discard type's info after the type checking pass.
The printer of the toplevel should work fine:
[1; "one"; 1.];;
- : (int -> string -> float -> unit) list =
(::) (1, (::) ("one", (::) (1., [])))
(The unoptimal printing is an unfortunate consequence of ensuring that values printed by the toplevel can be copy-pasted back to the top-level and yields the same value)
But this is only possible outside of the language itself: the toplevel printers can inspect the typing environment which is purposefully not possible in the language itself. Indeed functions like typeof would break parametricity. There is thus no universal printer function in OCaml (without looking at the internal memory representation) and no universal heterogeneous list printer.
If you want to print an heterogeneous list, there are three possible paths:
print a specific type of the heterogeneous list
let print_concrete ppf (x::y::z::rest) = Format.fprintf ppf "%f %f %f" x y z
(Contrary to appearance, this function is total: its type makes it impossible to use on lists with fewer than three elements)
Use heterogeneous lists that always pack a printing function along its main value
type 'a printer = Format.formatter -> 'a -> unit
type _ showable_list =
| [] : unit showable_list
| (::):
('a * 'a printer) * 'b showable_list
-> ('a -> 'b) showable_list
let rec print: type a. a showable_list printer =
fun ppf l -> match l with
| [] -> ()
| (a,printer) :: rest -> Format.fprintf ppf "%a# %a" printer a print rest
provide a matching heterogeneous list of printing functions
type 'a plist =
| []: unit plist
| (::): 'a printer * 'b plist -> ('a -> 'b) plist
let rec print: type l. l plist -> l list printer = fun printers ppf values ->
match printers, values with
| [], [] -> ()
| p :: prest, a :: rest -> Format.fprintf ppf "%a# %a" p a (print prest) rest
The fact that you often need to specialize the heterogeneous list type may make it worthwhile to introduce a functor for generating them:
module Hlist(Specialization: sig type 'a t end) = struct
open Specialization
type 'a list =
| []: unit list
| (::): 'a t * 'b list -> ('a -> 'b) list
end
then the previous specialized type can be constructed with
module Showable_list = Hlist(struct type 'a t = 'a * 'a printer end)
module Printer_list = Hlist (struct type 'a t = 'a printer end)
How do you do, Stackoverflow!
In Java practice there are some issues concerning partially defined functions. Sometimes it's convinient to separate an error handling from the calculation itself. We may utilize an approach called "Guard types" or "Guard decorators".
Consider the simple synthetic example: to guard the null reference. This can be done with the aid of the next class
public class NonNull<T> {
public take() {
return null != this.ref ? this.ref : throw new ExcptionOfMine("message");
}
public NotNull(T ref_) {
this.ref = ref_;
}
private T ref;
}
The question is:
Is there a way to implement the same "Guard type" in OCaml without touching its object model? I believe for the OCaml as the functional programming language to possess enough abstraction methods without objec-oriented technics.
You can use an abstract type to get the same effect. OCaml has no problem with null pointers. So say instead you want to represent a nonempty list in the same way as above. I.e., you want to be able to create values that are empty, but only complain when the person tries to access the value.
module G :
sig type 'a t
val make : 'a list -> 'a t
val take : 'a t -> 'a list
end =
struct
type 'a t = 'a list
let make x = x
let take x = if x = [] then raise (Invalid_argument "take") else x
end
Here's how it looks when you use the module:
$ ocaml
OCaml version 4.02.1
# #use "m.ml";;
module G :
sig type 'a t val make : 'a list -> 'a t val take : 'a t -> 'a list end
# let x = G.make [4];;
val x : int G.t = <abstr>
# G.take x;;
- : int list = [4]
# let y = G.make [];;
val y : '_a G.t = <abstr>
# G.take y;;
Exception: Invalid_argument "take".
There's a concept of Optional types, on which you can effectively pattern match. Example:
let optional = Some 20
let value =
match optional with
| Some v -> v
| None -> 0
You can use simple closures
let guard_list v =
fun () ->
if v = [] then failwith "Empty list"
else v
let () =
let a = guard_list [1;2;3] in
let b = guard_list [] in
print_int (List.length (a ())); (* prints 3 *)
print_int (List.length (b ())) (* throws Failure "Empty list" *)
or lazy values
let guard_string v = lazy begin
if v = "" then failwith "Empty string"
else v
end
let () =
let a = guard_string "Foo" in
let b = guard_string "" in
print_endline (Lazy.force a); (* prints "Foo" *)
print_endline (Lazy.force b) (* throws Failure "Empty string" *)
I would like to make my code generic over strings and arrays (any indexable type really) using the following signature:
module type Indexable = sig
type 'a t
val get : int -> 'a t -> 'a
end
module MyCode (I : Indexable) = struct ... end
But of course I cannot apply my signature to strings as follows:
module StrMyCode = MyCode(struct
type 'a t = string
let get i a = a.[i]
end)
Is there any way to fix this issue? Or perhaps a different aprroach? I know I can use arrays of characters in the worst case but I'd rather save my code from ugly casts and this is something that was on my mind before so I'd like to get a clear answer for this.
GADT can be used with the functorized approach:
module type Indexable = sig
type 'a t
val get: int -> 'a t -> 'a
end
module MyCode(I:Indexable) = struct
let head x = I.get 0 x
end
Arrays can of course be made Indexable trivially:
module IndexableArray = struct
type 'a t = 'a array
let get i x = x.(i)
end
For string, you can just use a GADT with a single constructor. Note however, that you have to put some type annotation for get in order to force the polymorphic type (otherwise, the inferred type is int -> char t -> char):
module IndexableString = struct
type 'a t = String: string -> char t
let of_string s = String s
let get: type a. int -> a t -> a =
fun i s -> match s with String s -> s.[i]
end
Here is something I made using GADTs. I'm just wrapping my head around them, so there may be something a little wrong here. But it seems to work as far as I can see (with OCaml 4):
type _ indexable =
| A : 'a array -> 'a indexable
| C : string -> char indexable
let index (type s) (x: s indexable) i : s =
match x with
| A a -> a.(i)
| C s -> s.[i]
let main () =
let x = A [| 1; 2 |] in
let y = C "abc" in
Printf.printf "%d\n" (index x 0);
Printf.printf "%c\n" (index y 1)
If I load into the toplevel, I get this:
val index : 'a indexable -> int -> 'a = <fun>
val main : unit -> unit = <fun>
# main ();;
1
b
- : unit = ()
#
This might not be as general as what you're looking for.
If you declare the element type of the indexable as a separate type, you can do something like this:
module type Indexable = sig
type t
type elt
val get : int -> t -> elt
end
module IndexableString : Indexable = struct
type t = string
type elt = char
let get i a = a.[i]
end
module MyCode (I : Indexable) = struct
(* My code implementation *)
end
module StrMyCode = MyCode(IndexableString)
For arrays, you can do more or less the same:
module ArrayIndexable = struct
type elt = char
type t = char array
let get i a = a.(i)
end
Now, if you wish to retain some flexibility with arrays, you may change the above into a functor:
module ArrayIndexable (E : sig type e end) : Indexable with type elt = E.e =
struct
type elt = e
type t = elt array
let get i a = a.(i)
end
It is more verbose than the polymorphic version you are looking for, but it let you encode both "indexable" types uniformly.
Is it really true that OCaml doesn't have a function which converts from a list to a set?
If that is the case, is it possible to make a generic function list_to_set? I've tried to make a polymorphic set without luck.
Fundamental problem: Lists can contain elements of any types. Sets (assuming you mean the Set module of the standard library), in contrary, rely on a element comparison operation to remain balanced trees. You cannot hope to convert a t list to a set if you don't have a comparison operation on t.
Practical problem: the Set module of the standard library is functorized: it takes as input a module representing your element type and its comparison operation, and produces as output a module representing the set. Making this work with the simple parametric polymoprhism of lists is a bit sport.
To do this, the easiest way is to wrap your set_of_list function in a functor, so that it is itself parametrized by a comparison function.
module SetOfList (E : Set.OrderedType) = struct
module S = Set.Make(E)
let set_of_list li =
List.fold_left (fun set elem -> S.add elem set) S.empty li
end
You can then use for example with the String module, which provides a suitable compare function.
module SoL = SetOfList(String);;
SoL.S.cardinal (SoL.set_of_list ["foo"; "bar"; "baz"]);; (* returns 3 *)
It is also possible to use different implementation of sets which are non-functorized, such as Batteries and Extlib 'PSet' implementation (documentation). The functorized design is advised because it has better typing guarantees -- you can't mix sets of the same element type using different comparison operations.
NB: of course, if you already have a given set module, instantiated form the Set.Make functor, you don't need all this; but you conversion function won't be polymorphic. For example assume I have the StringSet module defined in my code:
module StringSet = Set.Make(String)
Then I can write stringset_of_list easily, using StringSet.add and StringSet.empty:
let stringset_of_list li =
List.fold_left (fun set elem -> StringSet.add elem set) StringSet.empty li
In case you're not familiar with folds, here is a direct, non tail-recursive recursive version:
let rec stringset_of_list = function
| [] -> StringSet.empty
| hd::tl -> StringSet.add hd (stringset_of_list tl)
Ocaml 3.12 has extensions (7,13 Explicit naming of type variables and 7,14 First-class modules) that make it possible to instantiate and pass around modules for polymorphic values.
In this example, the make_set function returns a Set module for a given comparison function and the build_demo function constructs a set given a module and a list of values:
let make_set (type a) compare =
let module Ord = struct
type t = a
let compare = compare
end
in (module Set.Make (Ord) : Set.S with type elt = a)
let build_demo (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
let set = List.fold_right S.add xs S.empty in
Printf.printf "%b\n" (S.cardinal set = List.length xs)
let demo (type a) xs = build_demo (make_set compare) xs
let _ = begin demo ['a', 'b', 'c']; demo [1, 2, 3]; end
This doesn't fully solve the problem, though, because the compiler doesn't allow the return value to have a type that depends on the module argument:
let list_to_set (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
List.fold_right S.add xs S.empty
Error: This `let module' expression has type S.t
In this type, the locally bound module name S escapes its scope
A possible work-around is to return a collection of functions that operate on the hidden set value:
let list_to_add_mem_set (type a) set_module xs =
let module S = (val set_module : Set.S with type elt = a) in
let set = ref (List.fold_right S.add xs S.empty) in
let add x = set := S.add x !set in
let mem x = S.mem x !set in
(add, mem)
If you don't mind a very crude approach, you can use the polymorphic hash table interface. A hash table with an element type of unit is just a set.
# let set_of_list l =
let res = Hashtbl.create (List.length l)
in let () = List.iter (fun x -> Hashtbl.add res x ()) l
in res;;
val set_of_list : 'a list -> ('a, unit) Hashtbl.t = <fun>
# let a = set_of_list [3;5;7];;
val a : (int, unit) Hashtbl.t = <abstr>
# let b = set_of_list ["yes";"no"];;
val b : (string, unit) Hashtbl.t = <abstr>
# Hashtbl.mem a 5;;
- : bool = true
# Hashtbl.mem a 6;;
- : bool = false
# Hashtbl.mem b "no";;
- : bool = true
If you just need to test membership, this might be good enough. If you wanted other set operations (like union and intersection) this isn't a very nice solution. And it's definitely not very elegant from a typing standpoint.
Just extend the original type, as shown in
http://www.ffconsultancy.com/ocaml/benefits/modules.html
for the List module:
module StringSet = Set.Make (* define basic type *)
(struct
type t = string
let compare = Pervasives.compare
end)
module StringSet = struct (* extend type with more operations *)
include StringSet
let of_list l =
List.fold_left
(fun s e -> StringSet.add e s)
StringSet.empty l
end;;
Using the core library you could do something like:
let list_to_set l =
List.fold l ~init:(Set.empty ~comparator:Comparator.Poly.comparator)
~f:Set.add |> Set.to_list
So for example:
list_to_set [4;6;3;6;3;4;3;8;2]
-> [2; 3; 4; 6; 8]
Or:
list_to_set ["d";"g";"d";"a"]
-> ["a"; "d"; "g"]