OCaml overload numeric literal with Camlp4 - ocaml

I am writing a small script with some combinatorics utilities. When I need a numeric literal like 0 or 1 in a different type, I use _0 and _1, but this solution is less than ideal. Is it possible to use Camlp4 to reinterpret numeric literals within a given context or add a new type of numeric literal with a dedicated suffix?
open Num
let zero = num_of_int 0
let one = num_of_int 1
let _0 = zero
let _1 = one
(* some useful infix operators *)
let ( + ) = ( +/ )
let ( - ) = ( -/ )
let ( * ) = ( */ )
let ( < ) = ( </ )
let ( > ) = ( >/ )
let ( = ) = ( =/ )
let ( / ) numer denom =
if mod_num numer denom = _0
then div_num numer denom
else invalid_arg "division is not a total function"
(* factorial, naive *)
let rec fact n =
if n < _0
then invalid_arg "negative factorial"
else if n = _0
then _1
else
n * fact (n - _1)
(* naive algorithm *)
let choose n k = (fact n / fact k) / fact (n - k)

In short, no. Camlp4 is preprocessor of untyped parse tree. It cannot do such type sensitive thing.
If you would want (and I bet you will not), you can run type checking against the untyped parse trees in Camlp4 and infer the types of your special numerals, then replace them by corresponding values. It is theoretically possible but none has ever tried it, since P4's parse tree is completely different from the one of OCaml.
PPX preprocessor, which is meant to replace Campl4, has some hope, since it handles the same untyped parse tree as OCaml and therefore it is easy to apply OCaml type checker. TyPPX (https://bitbucket.org/camlspotter/typpx) is such a framework to provide APIs for type dependent preprocessing.

You may want to have a look to delimited overloading — it requires to qualify your constants by surrounding the expression e with M.(e) where M is the name of your module (you can define aliases).

Related

(sml) I'm going to make a function that prints a string tree beautifully in Lisp notation

In fact, I don't know exactly what "lisp notation" means.
So I tried to make it as similar to the list format as possible, but I can't express it like an example because () or (,) looks the same.
How can I represent a list like the example?
my sml code:
datatype 'a Tree = null | Tree of 'a Tree list | leaf of 'a;
fun prettyprint(null) = [] | prettyprint(leaf(v)) = [v] | prettyprint(Tree(h::t)) = prettyprint(h) # prettyprint(Tree(t)) | prettyprint(Tree([])) = []
val ex = Tree [leaf( 2 , 3 ,( 1 , 3 ), 4 ,( ( 3 ) ), 7 )];
Examples to represent:
val it = " ( 2 3 ( 1 3 ) 4 ( ( 3 ) ) 7 ) " : string
This may not be your exact solution. But Lisp is a family of programming languages with a long history and a distinctive, fully parenthesized prefix notation.
When representing source code in Lisp, the first element of an expression is commonly an operator or function name and any remaining elements are treated as arguments. This is called "prefix notation" or "Polish notation". As an example, the Boolean expression written 4 == (2 + 2) in C, is represented as (= 4 (+ 2 2)) in Lisp's prefix notation.
You can find many prefix (or preorder) algorithm in the net and implement it based your program language.

tuple access: Can't find a fixed record type

I wrote a function that is supposed to receive a list of tuples. I access the components of the tuples with # and the code compiles:
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
But another function that basically does the same thing, namely receiving a list of tuples and accessing those, causes an error.
fun validate ([]) = true
| validate (h::t) =
if 1 = (#1 h) then
true
else
false
Can't find a fixed record type. Found near #1
What is the difference here and why does the latter cause an error?
Edit
The first function actually does not compile on its own.
But this entire snippet does:
fun drop ([], n) = []
| drop (h::t, 0) = h::t
| drop (h::t, n) =
drop(t, n-1)
fun sts_linear (y, n) =
if y < (Math.sqrt(n)+1.0) then
let
(* x^2 + y^2 = n => x = sqrt(n-y^2) *)
val x = Math.sqrt(n - (y * y));
val xr = Real.realRound(x);
in
if (abs(x - xr) < 0.000000001) then
[(Real.trunc xr, Real.trunc y)]#sts_linear (y+1.0, n)
else
(
[]#sts_linear (y+1.0, n)
)
end
else []
fun recheck ([], n) = []
| recheck (h::t, n) =
if ((#1 h) * (#1 h)) + ((#2 h) * (#2 h)) = n then
h::recheck(t, n)
else
recheck(t, n)
fun sts (n) =
(
let
val pairs = sts_linear(0.0, Real.fromInt n);
in
recheck(drop(pairs, Real.ceil( Real.fromInt (length(pairs))/2.0 ) ), n)
end
)
Your first code doesn't compile, at least with SML/NJ:
If you got it to compile then it must have been in a nonstandard extension of SML.
The problem with both of your definitions is that there is no polymorphic idea of a tuple of arbitrary arity in SML. You can write functions to work on lists of pairs. You can write functions to work on lists of triples. But -- you can't write functions to work simultaneously on lists of pairs and lists of triples (at least if your function tries to do things with these pairs/triples as tuples).
One solution is to get rid of # and use pattern-matching to extract the components:
fun validate [] = true
| validate ((x,y)::t) =
if x = 1 then
true
else
false
But, if you really want to write a function which can polymorphically apply to either lists of pairs or list of triples (or quadruples,...), the easiest thing to do is to represent the pairs, triples, etc. as lists rather than tuples. Lists which contains lists of nonspecified size are not a problem in SML.
Trying to minimize this down, as I have seen the following work in SML/NJ
and i'm not aware of it actually being a compiler extension
val p1 = {x=0, y=0};
val p2 = {x=1, y=1};
val p3 = {x=1, y=1, z=1};
There is an awkward construct from a compiler error perspective
not many languages have errors that work in this fashion,
because the function is valid, but produces a type error
unless an invocation of the function exists to resolve the
type of 'record', thus to resolve the error more code must be added.
fun getFoo(field) = fn record => field record;
Without the following actual calling of the getX
the compiler cannot determine the type of record
of which the complete type information of ALL fields
of the record must be known to the compiler, not just the #x field.
let val getX = getFoo(#x);
val x1 = getX(p1);
val x2 = getX(p2);
val x3 = getFoo(#x)(p3);
in () end;
while the following commented out snippet results in an error because the types of
p1 and p3 are different, and so different invocations of getFoo
are required
(*
let val getX = getFoo(#x);
val x1 = getX(p1);
val x3 = getX(p3);
in () end;
*)
and the following is insufficient since it never resolves the record.
let val getX = getFoo(#x) in () end;

OCaml: building a list using a range in which the size id determined by a int cast from a float

I'm trying to build a list in OCaml that takes its end range variable from a function which returns an int cast from a float:
#require "batteries"
#require "pa_comprehension"
#require "core_kernel"
open Batteries
open Core_kernel
let factor_of num fact = num mod fact == 0 ;;
let limit num = Float.to_int (floor (sqrt num) ) ;;
the population of this list is not performed due to:
Error: This expression has type int but an expression was expected of type [<Downto | To ]
in both the (yummy) batteries list comprehension:
[? List: x | x <- 0--(limit num) ; factor_of num x ?] ;;
and the (slightly less but still quite readable) core_kernel List constructor:
List.(range 0 (limit num) |> filter ~f:( fun x -> factor_of num x) );;
I'm thinking that the return from limit num is trapped inside the (evil) monad that provides the Float.to_int function. This also happens when using Float.int_of_float, the type signatures are the same:
utop # Float.to_int;;
- : float -> int = <fun>
So... how do I get my int 'out' of the monad, or, if this is not the problem, what is going on and how do I cast to an actual int that is usable in this way?
Also, could someone point me to a decent 'What the hell are these things: Monads' tutorial for tiny, tiny brains? I am at my wits end with them.
UPDATE: The error was not caused by any monadic behaviour (or use at all, in fact) it was due to the incorrect use of an infix operator (mod) and a couple of other quirks in functional thinking that I have not completely understood. I'm not sure this post should still exist but maybe it is an example of the mistakes you can make when moving into the functional paradigm...?
I have managed to get to the source of the problem. Over thinking and a late night:
The error was not caused by any monadic behaviour (or use of monads at all, in fact) it was due to the incorrect use of an infix operator (mod) and a couple of other quirks in functional thinking that I have not completely understood. I'm not sure this post should still exist but maybe it is an example of the mistakes you can make when moving into the functional paradigm...?
Credit to helping me fix the issue to Str for helping me bend my mind.
Joe Gob has also pointed out the main issue in the code. More casting between float and int based of the types required by my functions.
This is the corrected code (deps.ml is a requirements file):
#use "deps.ml";;
open Batteries
open Core_kernel
let factor_of num fact = num mod fact == 0 ;;
let limit num = 2 * Float.to_int (floor (sqrt num)) ;;
let factor_list_of num =
[? List: x | x <- 1--(limit (Int.to_float num)) ; factor_of num x ?]
let sum_factors num = ( List.fold_right (+) (factor_list_of num) 0 )
let is_perfect num = sum_factors num == num
let is_abundant num = sum_factors num > num
let is_deficient num = sum_factors num < num
Basically I have been spoiled by Ruby, but I strongly advise rubyists to take up ocaml, it's has the closest style to ruby code of the functional languages.

How to reduce code clutter in this function?

The function tally below is really simple: it takes a string s as argument, splits it on non-alphanumeric characters, and tallies the numbers of the resulting "words", case-insensitively.
open Core.Std
let tally s =
let get m k =
match Map.find m k with
| None -> 0
| Some n -> n
in
let upd m k = Map.add m ~key:k ~data:(1 + get m k) in
let re = Str.regexp "[^a-zA-Z0-9]+" in
let ws = List.map (Str.split re s) ~f:String.lowercase in
List.fold_left ws ~init:String.Map.empty ~f:upd
I think this function is harder to read than it should be due to clutter. I wish I could write something closer to this (where I've indulged in some "fantasy syntax"):
(* NOT VALID SYNTAX -- DO NOT COPY !!! *)
open Core.Std
let tally s =
let get m k =
match find m k with
| None -> 0
| Some n -> n ,
upd m k = add m k (1 + get m k) ,
re = regexp "[^a-zA-Z0-9]+" ,
ws = map (split re s) lowercase
in fold_left ws empty upd
The changes I did above fall primarily into three groups:
get rid of the repeated let ... in's, consolidated all the bindings (into a ,-separated sequence; this, AFAIK, is not valid OCaml);
got rid of the ~foo:-type noise in function calls;
got rid of the prefixes Str., List., etc.
Can I achieve similar effects using valid OCaml syntax?
Readability is difficult to achieve, it highly depends on the reader's abilities and familiarity with the code. I'll focus simply on the syntax transformations, but you could perhaps refactor the code in a more compact form, if this is what you are really looking for.
To remove the module qualifiers, simply open them beforehand:
open Str
open Map
open List
You must open them in that order to make sure the List values you are using there are still reachable, and not scope-overridden by the Map ones.
For labelled parameters, you may omit the labels if for each function call you provide all the parameters of the function in the function signature order.
To reduce the number of let...in constructs, you have several options:
Use a set of rec definitions:
let tally s =
let rec get m k =
match find m k with
| None -> 0
| Some n -> n
and upd m k = add m k (1 + get m k)
and re = regexp "[^a-zA-Z0-9]+"
and ws = map lowercase (split re s)
in fold_left ws empty upd
Make multiple definitions at once:
let tally s =
let get, upd, ws =
let re = regexp "[^a-zA-Z0-9]+" in
fun m k ->
match find m k with
| None -> 0
| Some n -> n,
fun g m k -> add m k (1 + g m k),
map lowercase (split re s)
in fold_left ws empty (upd get)
Use a module to group your definitions:
let tally s =
let module M = struct
let get m k =
match find m k with
| None -> 0
| Some n -> n
let upd m k = add m k (1 + get m k)
let re = regexp "[^a-zA-Z0-9]+"
let ws = map lowercase (split re s)
end in fold_left ws empty M.upd
The later is reminiscent of the Sml syntax, and perhaps better suited to proper optimization by the compiler, but it only get rid of the in keywords.
Please note that since I am not familiar with the Core Api, I might have written incorrect code.
If you have a sequence of computations on the same value, then in OCaml there is a |> operator, that takes a value from the left, and applies in to the function on the right. This can help you to "get rid of" let and in. What concerning labeled arguments, then you can get rid of them by falling back to a vanilla standard library, and make your code smaller, but less readable. Anyway, there is a small piece of sugar with labeled arguments, you can always write f ~key ~data instead of f ~key:key ~data:data. And, finally, module names can be removed either by local open syntax (let open List in ...) or by locally shorcutting it to a smaller names (let module L = List in).
Anyway, I would like to show you a code, that contains less clutter, to my opinion:
open Core.Std
open Re2.Std
open Re2.Infix
module Words = String.Map
let tally s =
Re2.split ~/"\\PL" s |>
List.map ~f:(fun s -> String.uppercase s, ()) |>
Words.of_alist_multi |>
Words.map ~f:List.length

Empty character in OCaml

I am trying to do something fairly simple. I want to take a string such as "1,000" and return the string "1000".
Here was my attempt:
String.map (function x -> if x = ',' then '' else x) "1,000";;
however I get a compiler error saying there is a syntax error wrt ''
Thanks for the insight!
Unfortunately, there's no character like the one you're looking for. There is a string that's 0 characters long (""), but there's no character that's not there at all. All characters (so to speak) are 1 character.
To solve your problem you need a more general operation than String.map. The essence of a map is that its input and output have the same shape but different contents. For strings this means that the input and output are strings of the same length.
Unless you really want to avoid imperative coding (which is actually a great thing to avoid, especially when starting out with OCaml), you would probably do best using String.iter and a buffer (from the Buffer module).
Update
The string_map_partial function given by Andreas Rossberg is pretty nice. Here's another implementation that uses String.iter and a buffer:
let string_map_partial f s =
let b = Buffer.create (String.length s) in
let addperhaps c =
match f c with
| None -> ()
| Some c' -> Buffer.add_char b c'
in
String.iter addperhaps s;
Buffer.contents b
Just an alternate implementation with different stylistic tradeoffs. Not faster, probably not slower either. It's still written imperatively (for the same reason).
What you'd need here is a function like the following, which unfortunately is not in the standard library:
(* string_map_partial : (char -> char option) -> string -> string *)
let string_map_partial f s =
let buf = String.create (String.length s) in
let j = ref 0 in
for i = 0 to String.length s - 1 do
match f s.[i] with
| None -> ()
| Some c -> buf.[!j] <- c; incr j
done;
String.sub buf 0 !j
You can then write:
string_map_partial (fun c -> if c = ',' then None else Some c) "1,000"
(Note: I chose an imperative implementation for string_map_partial, because a purely functional one would require repeated string concatenation, which is fairly expensive in OCaml.)
A purely functional version could be this one:
let string_map_partial f s =
let n = String.length s in
let rec map_str i acc =
if i < n then
map_str (i + 1) (acc ^ (f (String.make 1 s.[i])))
else acc
in map_str 0 ""
Which is terminal recursive, but less performant than the imperative version.