show_module tediousness in utop - ocaml

I am using OCaml utop, with Core.Std module.
To see the help on a module, I have to follow the link of aliases like so:
utop # #show_module Array;;
module Array = Core_kernel.Std_kernel.Array
utop # #show_module Core_kernel.Std_kernel.Array;;
module Array = Core_kernel.Std_internal.Array
utop # #show_module Core_kernel.Std_internal.Array;;
module Array = Core_kernel.Core_array
And finally show_module on that will show the information. Is there a quicker way?

For completeness, the pull request mentioned by Daniel in the comments has been merged since, and now utop is smarter when it comes to #show_module.
utop # #show_module Array;;
module Array = Base__.Array
module Array = Base.Array
module Array :
sig
type 'a t = 'a array
val compare : ('a -> 'a -> int) -> 'a t -> 'a t -> int
val t_of_sexp : (Sexp.t -> 'a) -> Sexp.t -> 'a t
val sexp_of_t : ('a -> Sexp.t) -> 'a t -> Sexp.t
[...]
end

Related

Is there an universal printer in OCaml that detect the type?

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)

Inspect operator |> in OCaml's toplevel?

I'd like to see the type of the operator |>, which is of course defined as let |> x f = f x;;.
With other operators, like +, I can simple hit (+);; and the toplevel will tell me it's - : int -> int -> int = <fun>.
But with |>, it says:
Error: Failure: "|> must be applied to two arguments"
My question is, how can I inspect operator |> in OCaml's toplevel.
Append:
OK. Now I know it has something to do with Core. If I define it directly it's OK. But in Core environment it just breaks.
This is my .ocamlinit:
(* Added by OPAM. *)
let () =
try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
with Not_found -> ()
;;
#use "topfind";;
#thread;;
#camlp4o;;
#require "core.top";;
#require "core.syntax";;
open Core.Std;;
It works for me. Here's a complete command line session:
$ ocaml
OCaml version 4.01.0
# let (|>) x f = f x;;
val ( |> ) : 'a -> ('a -> 'b) -> 'b = <fun>
# (|>);;
- : 'a -> ('a -> 'b) -> 'b = <fun>
#
Update
(Pascal Cuoq clearly has the right answer in the comments below. :-)

How to examine a module/signature at ocaml top level?

Please: I would like to examine a module's signature; is there a function to do this? Just typing the name of the module doesn't work:
# List ;;
Error: Unbound constructor List
In fact I want to do this for modules I define on the interactive top level.
Sorry if the answer is obvious - hard to search for this! Thanks.
The standard trick for this is to make a new module synonym:
# module Mylist = List;;
module Mylist :
sig
val length : 'a list -> int
val hd : 'a list -> 'a
val tl : 'a list -> 'a list
. . .
val sort : ('a -> 'a -> int) -> 'a list -> 'a list
val stable_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val fast_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val merge : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
end
#
Update
Since OCaml 4.02 this trick no longer works. Instead there is a toplevel directive for the purpose:
# #show_module List;;
module List :
sig
val length : 'a list -> int
val hd : 'a list -> 'a
val tl : 'a list -> 'a list
. . .
val sort : ('a -> 'a -> int) -> 'a list -> 'a list
val stable_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val fast_sort : ('a -> 'a -> int) -> 'a list -> 'a list
val sort_uniq : ('a -> 'a -> int) -> 'a list -> 'a list
val merge : ('a -> 'a -> int) -> 'a list -> 'a list -> 'a list
end
In OCaml versions >= 4.02, you can now also do this in the interactive interpreter:
# #show_module List;;
module List :
sig
val length : 'a list -> int
...
end
Or just use #show List;;

Signature Mismatch ocaml

First the code:
module type ENV_CORE =
sig
type variable
type 'a environment
exception Unbound_variable
val empty : unit -> variable
val bind : 'a -> 'a environment -> 'a environment
val unbind : variable -> 'a -> 'a environment -> 'a environment
val is_bound : variable -> 'a environment -> bool
val lookup : variable -> 'a environment -> bool
val fold : (variable -> 'a -> 'b -> 'b) -> 'a environment -> 'b -> 'b
end;;
module EnvCoreList : ENV_CORE =
struct
type variable = string list
type 'a environment = variable * variable -> 'a
exception Unbound_variable
let empty () = []
let bind elt l = elt::l
let rec unbind elt l =
match l with
|[] -> raise Unbound_variable
|a::r -> if (elt = a)
then r
else a::(unbind elt r)
let rec is_bound elt l =
match l with
|[] -> raise Unbound_variable
|a::r -> if (elt = a)
then true
else is_bound elt r
let rec lookup elt l =
match l with
|[] -> false
|a::r -> if (elt = a)
then true
else lookup elt r
let rec fold f rho gamma =
match rho with
|[] -> gamma
|a::r -> f a (fold f r gamma)
end;;
When I compile it I get the following error:
Error: Signature mismatch:
Modules do not match:
sig
type variable = string list
type 'a environment = variable * variable -> 'a
exception Unbound_variable
val empty : unit -> 'a list
val bind : 'a -> 'a list -> 'a list
val unbind : 'a -> 'a list -> 'a list
val is_bound : 'a -> 'a list -> bool
val lookup : 'a -> 'a list -> bool
val fold : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b
end
is not included in
ENV_CORE
Values do not match:
val bind : 'a -> 'a list -> 'a list
is not included in
val bind : 'a -> 'a environment -> 'a environment
What I don't understand is how the more specific type isn't included in the more general type?
I couldnt find any similar questions and havent been able to resolve this issue.
Thanx
There's no obvious relation between the types 'a list and 'a environment. I don't see why you would consider either to be more general than the other.
It seems to me you should either change your definition of environment in your implementation, or you should rewrite bind so that it works on the type you specify for environment.

"Error: The function applied to this argument has type ..." when using named parameters

I'm currently working through "Real Word OCaml", and one of the basic examples with named / labeled parameters doesn't seem to work (using utop 4.01.0):
let languages = ["OCaml"; "Perl"; "C"];;
List.map ~f:String.length languages;;
Produces:
Error: The function applied to this argument has type 'a list -> 'b list
This argument cannot be applied with label ~f
Whereas:
List.map String.length languages;;
Produces the expected output [5; 4; 1].
caml.inria.fr mentions that:
In the core language, as in most languages, arguments are anonymous.
Does this mean that I have to include some kind of external library to make this code work ?
EDIT
Here's my ~/.ocamlinit file (as per the installation instructions for the book):
(* Added by OPAM. *)
let () =
try Topdirs.dir_directory (Sys.getenv "OCAML_TOPLEVEL_PATH")
with Not_found -> ()
;;
#use "topfind"
#camlp4o
#thread
#require "core.top"
#require "core.syntax"
As mentioned in #rafix's comment, this can be fixed by putting
open Core.Std ;;
first.
The standard List.map method isn't defined with the label ~f. The type of List.map is ('a -> 'b) -> 'a list -> 'b list, but if you wanted to use the "~f" label, it would have to be "f:('a->'b) -> 'a list -> 'b list". If you wanted to define your own, you would have to define it as such:
let rec myMap ~f l = match l with
| [] -> []
| h::t -> (f h) :: (myMap ~f t);;
val myMap : f:('a -> 'b) -> 'a list -> 'b list = <fun>
and then you could call it like you wanted:
myMap ~f:String.length languages
Cheers!