Unexpected string equality results - ocaml

I have some OCaml code:
let (&>) : ('x -> 'y) -> ('y -> 'z) -> ('x -> 'z) =
fun g f x -> x |> g |> f
let soi x = string_of_int x
let sof x = string_of_float x
let fos x = float_of_string x
let ios x = int_of_string x
let clear_int = ios &> soi
let is_int_clear (x: string) =
let targ = clear_int x in
let _ = print_endline x in
let _ = print_endline targ in
x == targ
let ccc = is_int_clear "123"
let scc = if ccc then "succ" else "fail"
let () = print_endline scc
I think "123" should be equal to "123" but output this:
123
123
fail
"123" was not equal "123".
Why and how to fix it?

The fault in your logic lies in using == which tests for physical equality. This is checking that the two strings reside at the same location in memory.
You wanted to use = which tests for structural equality: whether the two values contain the same information.
The change is very simple.
let is_int_clear (x: string) =
let targ = clear_int x in
let _ = print_endline x in
let _ = print_endline targ in
x = targ

Related

Is this use of Obj.magic necessary?

I am reading a repository and I encountered this function in the body of some Yojson json parsing code:
let load_problems channel =
let open Yojson.Basic.Util in
let j = Yojson.Basic.from_channel channel in
...
let rec unpack x =
try magical (x |> to_int) with _ ->
try magical (x |> to_float) with _ ->
try magical (x |> to_bool) with _ ->
try
let v = x |> to_string in
if String.length v = 1 then magical v.[0] else magical v
with _ ->
try
x |> to_list |> List.map ~f:unpack |> magical
with _ -> raise (Failure "could not unpack")
in
...
where magical = Obj.magic. I understand what Obj.magic is (it's the equivalent to Unsafe.Coerce in Haskell), but I don't see why a type coercion is necessary here. The Yojson.Basic.Util functions the author uses should already either succeed or fail to do this conversion. Any intuition?
EDIT:
I feel I was depriving #glennsl of context, so here is the immediately following passage in which unpack is used:
let tf = j |> member "tasks" |> to_list |> List.map ~f:(fun j ->
let e = j |> member "examples" |> to_list in
let task_type = j |> member "request" |> deserialize_type in
let examples = e |> List.map ~f:(fun ex -> (ex |> member "inputs" |> to_list |> List.map ~f:unpack,
ex |> member "output" |> unpack)) in
let maximum_frontier = j |> member "maximumFrontier" |> to_int in
let name = j |> member "name" |> to_string in
let task =
(try
let special = j |> member "specialTask" |> to_string in
match special |> Hashtbl.find task_handler with
| Some(handler) -> handler (j |> member "extras")
| None -> (Printf.eprintf " (ocaml) FATAL: Could not find handler for %s\n" special;
exit 1)
with _ -> supervised_task) ~timeout:timeout name task_type examples
in
(task, maximum_frontier))
in
There are a number of different task_handlers, but the one I happen to be concerned with is defined as follows:
(fun extras ?timeout:(timeout = 0.001) name ty examples ->
let open Yojson.Basic.Util in
let cost_matters =
try
extras |> member "costMatters" |> to_bool
with _ -> assert false
in
let by = match examples with
| [([0],y)] ->
Bigarray.(Array1.of_array int8_unsigned c_layout (Array.of_list y))
| [([1],y)] ->
Bigarray.(Array1.of_array int8_unsigned c_layout (Array.of_list y))
| _ -> failwith "not a turtle task" in
{ name = name ;
task_type = ty ;
log_likelihood =
(fun p ->
try
match run_recent_logo ~timeout p with
| Some(bx,cost) when (LogoLib.LogoInterpreter.fp_equal bx by 0) ->
(if cost_matters then (0.-.cost)*.10. else 0.)
| _ -> log 0.
with (* We have to be a bit careful with exceptions if the
* synthesized program generated an exception, then we just
* terminate w/ false but if the enumeration timeout was
* triggered during program evaluation, we need to pass the
* exception on
*)
| UnknownPrimitive(n) -> raise (Failure ("Unknown primitive: "^n))
| EnumerationTimeout -> raise EnumerationTimeout
| _ -> log 0.0)
});;
The author also uses ;; in a lot of files..another quirk.

How to use ocaml-re

I am currently trying to use ocaml-re. Documentation is sparse. I was wondering how I would, for instance, do the equivalent:
Str.regexp "example \\([A-Za-z]+\\)" using Re.Perl? I think it would help me to naturally get the rest of the documentation on my own. Thank you!
Bonus points if you convert this code from Str to Re.Perl:
let read_filename = "example.ts"
let filename = "example2.ts"
let () =
CCIO.(
let modify_file ~chunks =
let r = Str.regexp "example \\([A-Za-z]+\\)" in
match chunks () with
None -> chunks (* is the same as (fun () -> None) *)
| Some chunks ->
let test_chunks = Str.replace_first r "\\1" chunks in (* compute once *)
(fun () -> Some test_chunks) in
with_in read_filename
(fun ic ->
let chunks = read_chunks ic in
let new_chunks = modify_file ~chunks in
with_out ~flags:[Open_binary] ~mode:0o644 filename
(fun oc ->
write_gen oc new_chunks
)
)
)
Don't use Re.Perl, Re's API is much simpler. You can constructor your re with:
let re =
let open Re in
alt [rg 'A' 'Z'; rg 'a' 'z'] (* [A-Za-z] *)
|> rep1a (* [A-Za-z]+ *)
|> group (* ([A-Za-z]+) *)
|> compile

Ocaml won't let me name my List

the code :
open Hashtbl;;
type 'a option = None | Some of 'a;;
let ht = create 0;;
let rec charCount fd =
let x =
try Some (input_char fd)
with End_of_file -> None
in
match x with
| Some c ->
let v =
try find ht c
with Not_found -> 0
in
replace ht c (v+1);
charCount fd
| None -> ();;
let loadHisto fn =
let fd = open_in fn in
charCount fd;;
let rec printList l = match l with
| [] -> print_newline ()
| h::t -> print_char h; print_string " "; printList t;;
let hashtbl_keys h = Hashtbl.fold (fun key _ l -> key :: l) h [];;
let compare_function a b = compare (find ht b) (find ht a);;
let akeys = List.sort compare_function (hashtbl_keys ht);;
printList (List.sort compare_function (hashtbl_keys ht));;
printList akeys;;
and the result :
ocaml histo.ml
e t s u a i n p j (*here is the first printList*)
(*and here should be the second one, but there is only a blank*)
Here is the problem :
I sorted a list, and tried to display it's content but as you can see, it doesn't seem like I can give a name to my resulting List
Edit :
I don't think it's a buffer problem because even if I only print akeys, there is nothing
Edit : I added the code asked for below
And ht is a hashtbl, and it contains what it should contain (I checked this)

Print equivalence classes in Coq format

Follow the counter example from my previous question: Error when convert to Boolean matrix .
let entries = [("name", ["string"]); ("label", ["nonNegativeInteger"; "symbol"]);
("symbol", ["name"; "symbol"; "symbol"; "label"]); ("var", ["string"]);
("term", ["var"; "symbol"; "term"]); ("rule", ["term"; "term"]);
("rules", ["rule"]); ("dps", ["rules"]); ("trs", ["rules"]);
("usableRules", ["rules"]);
("number", ["integer"; "integer"; "positiveInteger"]);
("coefficient",["number"; "minusInfinity"; "plusInfinity"; "vector"; "matrix"])
("vector", ["coefficient"]); ("matrix", ["vector"])]
let defined = ["name"; "label"; "symbol"; "var"; "term"; "rule"; "rules";
"dps"; "trs"; "usableRules"; "number"; "coefficient"; "vector"; "matrix"]
let undefined = ["string"; "nonNegativeInteger"; "integer"; "positiveInteger";
"minusInfinity"; "plusInfinity"]
I computed with these functions: (more details please see here: Transitive closure and equivalence classes and Asking about return type, list and set data structure in OCaml)
let rec position x = function
| [] -> raise Not_found
| y :: ys -> if x = y then 0 else 1 + position x ys
let len_undefined = List.length undefined
let num_of_name xsds undefined len_undefined s =
try (position s xsds) + len_undefined;
with Not_found -> position s undefined
let name_of_num xsds undefined len_undefined k =
if k < len_undefined then
List.nth undefined k else
List.nth xsds (k - len_undefined)
let matrix =
let len = List.length defined + len_undefined in
let boolmat = Array.make_matrix len len false in
List.iter (fun (s, strs) ->
let pos1 = num_of_name defined undefined len_undefined s in
List.iter (fun t ->
let pos2 = num_of_name defined undefined len_undefined t in
boolmat.(pos1).(pos2) <- true) strs) entries;
boolmat
let transClosure m =
let n = Array.length m in
for k = 0 to n - 1 do
let mk = m.(k) in
for i = 0 to n - 1 do
let mi = m.(i) in
for j = 0 to n - 1 do
mi.(j) <- max mi.(j) (min mi.(k) mk.(j))
done;
done;
done;
m;;
let eq_class m i =
let column = m.(i)
and set = ref [] in
Array.iteri begin fun j l ->
if j = i || column.(j) && m.(j).(i) then
set := j :: !set else ignore l
end column;
!set;;
let eq_classes m =
let classes = ref [] in
Array.iteri begin fun e _ ->
if not (List.exists (List.mem e) !classes) then
classes := eq_class m e :: !classes
end m;
!classes;;
let cmp_classes m c c' = if c = c' then 0 else
match c, c' with
| i :: _, j :: _ -> if m.(i).(j) then 1 else -1
| _ -> assert false
let sort_eq_classes m = List.sort (cmp_classes m);;
let order_xsds =
let tc_xsds = transClosure matrix in
let eq_xsds = eq_classes tc_xsds in
let sort_eq_xsds = sort_eq_classes tc_xsds eq_xsds in
sort_eq_xsds
let print =
let f elem =
print_int elem ; print_string " "
in List.iter f (List.flatten order_xsds);;
let xsds_of_int =
List.map (List.map (name_of_num defined undefined len_undefined))
let xsds_sort = xsds_of_int order_xsds
let print_string =
let f elem =
print_string elem ; print_string " \n"
in List.iter f (List.flatten xsds_sort);;
I try to print the result to see the sorted equivalence classes :
var name symbol label plusInfinity minusInfinity positiveInteger integer number
matrix vector coefficient nonNegativeInteger string term rule rules usableRules
trs dps
Because I have to print in Coq format, I have to make the file output combine, so the result I want to print in order of the results of the equivalence classes, when it see an equivalence classes ("label" -"symbol"; "coefficient" - "matrix" - "vector") it should print:
EDIT:
Inductive label := all the type label depends
with symbol := all the type symbol depends.
For example:
Inductive label :=
| Label : nonNegativeInteger -> symbol -> label
with symbol :=
| Symbol : name -> symbol -> symbol -> label -> symbol.
when it is one type depends it will print for me, for example:
Definition name := string.
and when it is more than 2 depends type,
Inductive numer := all the type number depends.
for example:
Inductive number :=
|Number : integer -> integer -> positiveInteger -> number.
I think the list of type in undefined type should print before and after it will print in the result of the list after sorted (and all the type of undefined list should not print again), for example the result I expect like this:
Definition string := string.
Definition nonNegative := int.
...
Definition var := string.
Definition name := string.
Inductive label := ...
with symbol := ...
and so on
Could you please help me?
I might be confused but I think you're just looking for the Printf module and String.concat? e.g.
List.iter
(fun name ->
Printf.printf "Definition %s := %s.\n" name (defn_of name))
undefined;
List.iter
(fun eqvclass ->
Printf.printf "Inductive %s.\n"
(String.concat "\nwith "
(List.map
(fun name ->
Printf.sprintf "%s := %s" name (defn_of name))
eqvclass)))
order_xsds
(where defn_of gives you the right-hand side of the definitions).

Change application order in OCaml

Is there a way to change the order from left-associative to right-associative, except parentheses? For example in Haskell you can write foo $ bar b and foo will be applied to a result from bar b.
let a x = x * 4;;
let b y = y + 2;;
let c = a ??? b 3;;
print_int c;;
Should print 20
Sure, you can define it yourself:
let (###) f x = f x
Then, a ### b 3 evaluates to 20. Make sure to select a starting symbol such that it is right-associative (see here) ($... is left-associative)
You just have to define a symbol for such applications:
let (###) f x = f x ;;
And then
let f x = x * 4;;
let g y = y + 2;;
let a = f ### g 3;;
print_int a;;
does print 20.
Note that the next version of OCaml (3.13 or 4.00) will provide builtin primitives for applications that avoid creating intermediate partially applied functions:
external (###) : ('a -> 'b) -> 'a -> 'b = "%apply"
external (|>) : 'a -> ('a -> 'b) -> 'b = "%revapply"
The last one is the opposite of %apply:
print_int (3 |> g |> f);;
Note that you cannot use ($) as it is left-associative in the definition of the OCaml parser:
let ($) f x = f x ;;
let a = f $ g 3;;  (* ok ! ??? *)
let a = f $ g $ g 3;; (* ERROR -> g is not an integer,
because OCaml computes (f $ g) first *)