OCaml function name as string - ocaml

I sometimes write functions that make the assumption that some arguments cannot occur. If they do, this is a bug and I fail:
let foo = function
| 0 -> ()
| _ -> failwith "foo: bad argument"
If I rename the function later on, I have to remember to also change the string. Is there a way to do this in a more systematic manner? My mind wanders around solutions like
| _ -> failwith (FUNCTION_NAME ^ ": bad argument")
where FUNCTION_NAME is a string variable that the compiler or interpreter will instantiate. But I have no idea whether something like this even works in OCaml. If not, is there a best practice?

There is a set of values available for debugging and error reporting.
OCaml 4.12 introduced __FUNCTION__:
val __FUNCTION__ : string
__FUNCTION__ returns the name of the current function or method, including any enclosing modules or classes.
They might be useful if you don't want to use assert false as suggested by #SteveVinoski.
__LOC__ : string
__FILE__ : string
__LINE__ : int
__MODULE__ : string
__POS__ : string * int * int * int
There are also fancier forms that you can use to wrap an expression to determine its extent in the source.
These are documented in the Stdlib module.

I think you should try as much as possible to use more specific types so that the compiler can prevent you from calling your functions with invalid input.
If you really don't find a way to tell the type system what you want, try harder, and if you really can't, then use assert which as Steve told you will give you some precious debugging information (file and line number are much more useful than function name since chances are high your function doesn't have a name).

Since 4.12.0, __FUNCTION__ will return the function name.
There are also a number of other debugging variables defined in Stdlib:
val __LOC__ : string
val __FILE__ : string
val __LINE__ : int
val __MODULE__ : string
val __POS__ : string * int * int * int
val __FUNCTION__ : string
val __LOC_OF__ : 'a -> string * 'a
val __LINE_OF__ : 'a -> int * 'a
val __POS_OF__ : 'a -> (string * int * int * int) * 'a

Related

Ocaml Conversion String to int to char

I need to implement this function somewhere
String.get: string -> int -> char
I have tried this one but it does not seem to work
let String.get = fun x -> char_of_int(int_of_string x) ;;
The error I get is:
let String.get = fun x -> char_of_int(int_of_string x) ;;
^^^
Error: Syntax error
String.get is a syntax to denote the function get in module String. The syntax can not be used to (re)define a function as you wrote.
The function is documented here:
val get : string -> int -> char
String.get s n returns the character at index n in string s. You can also write s.[n] instead of String.get s n.
Raise Invalid_argument if n not a valid index in s.
What you are trying to implement is different, you are trying to read, from the string, an integer, and then convert it to a digit char (?)
Depending on what your actual requirements are, you might be asked to reimplement String.get on your own, so for example you would pick a different name in your current module (for now, this is sufficient, you don't need to bother about modules):
let char_at s n = ...
Or maybe you do actually need to convert from an integer. Please clarify your question.

Why can't the compiler match this function type?

I have an issue with the OCaml compiler I can't explain myself. The following code won't compile:
open Postgresql
let get_nodes conn =
ignore (conn#exec "SELECT * FROM node_full")
let () =
let c = new connection () in
ignore (get_nodes c)
It gives the following error:
File "test.ml", line 8, characters 20-21:
Error: This expression has type Postgresql.connection
but an expression was expected of type < exec : string -> 'a; .. >
Types for method exec are incompatible
(Line 8 is the last line)
But the following piece of code compiles without error (and works as expected, in the full version of the code):
open Postgresql
let get_nodes (conn:connection) =
ignore (conn#exec "SELECT * FROM node_full")
let () =
let c = new connection () in
ignore (get_nodes c)
The only difference is that I specified the type of the conn parameter in the get_nodes function.
Does someone understand what is going on here ? This is the first time I have to specify a type myself in order to make the code work, and I am a daily OCaml user ...
Additionnaly, I don't see, in the error message, why the types involved are not compatible, here is the type of the exec function:
method exec :
?expect:Postgresql.result_status list ->
?params:string array ->
?binary_params:bool array ->
string -> Postgresql.result
and the type of the get_all function from Postgresql.result:
method get_all : string array array
Happy new year !
Well, nlucaroni has pointed out that this has been answered in a simpler form at Optional argument in a method with ocaml, but here's a short description of what I got by reading that page.
Your call to exec gives it the inferred type string -> 'a. This isn't at all like the type of the exec method of a Postgresql connection, which has three optional parameters. One way to fix it is to do what you did: declare the type of the conn parameter. You could also just declare the optional parameters of the exec method, maybe something like this:
ignore (
(conn#exec :
?expect: 'a ->
?params: 'b ->
?binary_params: 'c ->
string -> 'd) "SELECT * FROM node_full"
)

Converting OCaml strings to format6

The following code does not compile:
let x = "hello" in
Printf.printf x
The error is:
Error: This expression has type string but an expression was expected of type
('a, out_channel, unit) format =
('a, out_channel, unit, unit, unit, unit) format6
1) Can someone give an explanation of the error message?
2) And why would a string cannot be passed to printf ?
The first argument to printf must be of type ('a, out_channel, unit) format not string. String literals can be automatically converted to an appropriate format type, but strings in general can't.
The reason for that is that the exact type of a format string depends on the contents of the string. For example the type of the expression printf "%d-%d" should be int -> int -> () while the type of printf "%s" should be string -> (). Clearly such type checking is impossible when the format string is not known at compile time.
In your case you can just do printf "%s" x.
As sepp2k points out, in OCaml printf formats have a distinct type, and are not simply strings. String literals are converted automatically to printf formats, but x is not a string literal. If you want to give a name to a format, you can convert it explicitly yourself:
> let x = format_of_string "hello" in Printf.printf x
hello- : unit = ()
You can also cause the implicit conversion by specifying a type for x, but the types of formats are so complicated this is quite painful:
# let (x: ('a,'b,'c,'d,'d,'a) format6) = "hello" in Printf.printf x;;
hello- : unit = ()
(I personally don't understand the format6 type.)

Idea working in types

Please see details in My previous question
1) cpf0.ml:
type string = char list
type name = string
type symbol =
| Symbol_name of name
2) problem.ml:
type symbol =
| Ident of Cpf0.string
In this problem.ml it has two definitions for type string, and surely it's giving me an error, but is it posible that I can make them have a same type? I need an idea.
module Str = struct type t = string end;;
module StrOrd = Ord.Make (Str);;
module StrSet = Set.Make (StrOrd);;
module StrMap = Map.Make (StrOrd);;
module SymbSet = Set.Make (SymbOrd);;
let rec ident_of_symbol = function
| Ident s -> s
let idents_of_symbols s =
SymbSet.fold (fun f s -> StrSet.add (ident_of_symbol f) s) s StrSet.empty;;
This expression has type Cpf0.string = char list but an expression was expected of type Util.StrSet.elt = string
You can use the name "string" for different types in different modules if you like, though (as Basile Starynkevitch points out) it's confusing. It would be better to pick a different name. If you really need to reuse the name, you can specify the module every time. If you don't specify a module, you'll get the predefined meaning (or the meaning from the innermost opened module).
It seems to me the problem in your quoted code is that this line:
module Str = struct type t = string end;;
doesn't specify a module name for string, so it refers to the predefined string. It seems possible you wanted to say:
module Str = struct type t = Cpf0.string end;;
It's hard to tell, however. There's not enough context for me to really understand what you're trying to do.
string is a predefined type in Ocaml (ie in the Pervasives module); it is e.g. the type of string literal constants like "this string". Use some other name (otherwise you, and any one reading your code, will be very confused)

OCaml: get value's type name

Is is possible to print value's name in OCaml, for example if I have
type my_type =
| MyType_First of int
| MyType_Second of string
and then do something like:
let my_value = MyType_First 0 in
print_string ("my_value is of type " ^ String.from_type my_value ^ ".\n";
can I get "my_value is of type MyType_First." ?
Thank you.
Monomorphic solution:
let from_type = function
| MyType_First _ -> "MyType_First"
| MyType_Second _ -> "MyType_Second"
Polymorphic solution: none. (AFAIK, lexical tokens corresponding to constructors are not recorded in the bytecode/binary, even when debugging flags are specified. The only thing one could do is to print the integer ‘identifier’ for the constructor, using some dark Obj.magic.)
What you want is a simpler form of generic print and is not available in OCaml as such, but some workarounds exist - e.g. deriving.