Inspect operator |> in OCaml's toplevel? - ocaml

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. :-)

Related

Understanding relation between let and val in interactive mode

let app = fun f -> fun x -> f (x);;
(*val app : ('a -> 'b) -> 'a -> 'b = <fun>*)
let app = fun f -> fun x -> x (f+1);;
(*val app : int -> (int -> 'a) -> 'a = <fun>*)
let app = fun f -> fun x -> x (f);;
(*val app : 'a -> ('a -> 'b) -> 'b = <fun>*)
let app2 = fun f -> fun g -> fun x -> g ( f x );;
(*val app2 : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c = <fun>*)
let app2 = fun f -> fun g -> fun x -> f (g x );;
(*val app2 : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>*)
let app2 = fun f -> fun g -> fun x -> g (f x+1);;
(*val app2 : ('a -> int) -> (int -> 'b) -> 'a -> 'b = <fun>*)
let app2 = fun f -> fun g -> fun x -> f (g x+1 );;
(*val app2 : (int -> 'a) -> ('b -> int) -> 'b -> 'a = <fun>*)
let app3 = fun f -> fun g -> fun x -> g f x+1 ;;
(*val app3 : 'a -> ('a -> 'b -> int) -> 'b -> int = <fun>*)
How do I know what happens in the val line without tapping enter on the let app line.
To be more specific I dont understand the relation between let and val.
For example, for the first one:
let app = fun f -> fun x -> f (x);;
(*val app : ('a -> 'b) -> 'a -> 'b = <fun>*)
What I see is that the first x takes the name 'a
and after it goes to the f which takes the name 'b
and after it goes to the fun x which is 'a again
and after it goes to the fun y which is 'b again.
But it is clearly not the case with other functions.
How do I know how they are related?
Someone has put the types of these functions in comments below the actual code. Comments in OCaml are surrounded by (* and *).
These type signatures are identical to what you'd see in an OCaml toplevel. You enter an expression, followed by ;;, this code is evaluated, and you're shown the resulting value.
Consider:
# 4 + 5;;
- : int = 9
# let a = 4 + 5;;
val a : int = 9
#
The val only shows up if I've introduced a name for the value. In either case we're shown the type of the resulting value and the value itself.
When you see things like 'a and 'b you're seeing type variables that OCaml infers when it can't infer a specific type. This very recent question is worth reading.
let is used to create name-bindings(alternatively named definitions if you would like to call it), where a binding will have a name and will be bound to an expression, which when evaluated will produce a value.
fun is used to create/define anonymous function, Anonymous functions are function expression which means an expression of type function, which when evaluated given its arguments will produce a value, and this function expression can itself be passed around like any other regular value.. and this function expression is bound using a let.
For example
let app = fun f -> fun x -> x (f+1)
In this case, we are defining a name app which will be bound to the expression produced by fun on the right. The fun takes a parameter f whose type will be inferred by the compiler once it is done processing the body of that function expression. The same applies to the next function expression which takes a parameter named x.
By looking at the right-most expression, which is responsible for generating the reduced value, we see f getting applied to the operator + and so f will receive it's type from that expression. And then x (...) entails a function application, so the x will receive it's type from that expression.
And we can go on applying the same to every expression cited in the question.
Essentially, let bindings, lambda expressions, type inference, function application, function expression etc... are some of the topics one should get acquainted with to understand what's going on.

Example code from "Real World Ocaml" doesn't run as intended.

I'm learning ocaml so it's maybe trivial.
When I try to build executable of this code:
open Core.Std
let build_counts () =
In_channel.fold_lines stdin ~init:[] ~f:(fun counts line ->
let count =
match List.Assoc.find counts line with
| None -> 0
| Some x -> x
in
List.Assoc.add counts line (count + 1)
)
let () =
build_counts ()
|> List.sort ~cmp:(fun (_,x) (_,y) -> Int.descending x y)
|> (fun l -> List.take l 10)
|> List.iter ~f:(fun (line,count) -> printf "%3d: %s\n" count line)
I get this error:
Error: This pattern matches values of type 'a option
but a pattern was expected which matches values of type
equal:(Stdio__.Import.string -> Stdio__.Import.string -> bool) ->
'b option
Where is the problem?
Link: https://realworldocaml.org/v1/en/html/files-modules-and-programs.html
Below is the type signature for List.Assoc.find:
('a, 'b) Base__List.Assoc.t -> equal:('a -> 'a -> bool) -> 'a -> 'b option
The first argument is the associative list (counts in the example). The last argument (of type 'a) is the key you're looking for (this is line in your example). There is another argument, however, of type 'a -> 'a -> bool which labeled equal. It's pretty straight-forward that it is a comparison function used by List.Assoc.find to see whether two keys are equals.
In the case where 'a is string, a simple (=) is enough. You can fix your code by replacing your match line with the following:
match List.Assoc.find counts ~equal:(=) line with
The List.Assoc.add function follows the same pattern. You should replace the last line of the build_counts function with the following:
List.Assoc.add counts ~equal:(=) line (count + 1)
As a side-note, Real World OCaml is getting quite old (this is why some examples are outdated), and the authors are working on a second edition.

Why this OCaml code does not subject to the value restriction

I don't understand that the function (my_path_mapper) doesn't subject to the value restriction.
# let rec my_map ~f l =
match l with
[] -> []
| h::t -> f h::my_map f t;;
val my_map : f:('a -> 'b) -> 'a list -> 'b list = <fun>
# let my_path_mapper =
my_map ["/usr/sbin"; "/usr/bin"; "/sbin"; "/bin"; "/usr/games"; "/usr/local/games"];;
val my_path_mapper : f:(string -> 'a) -> 'a list = <fun>
Please teach me Why ?
OCaml has a "relaxed value restriction." You can read about it here:
Jacques Garrigue, Relaxing the Value Restriction
Here is a previous discussion on StackOverflow:
When does the relaxed value restriction kick in in OCaml?

show_module tediousness in utop

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

"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!