Generating strings based on a given grammar sometimes results in non stop printing - c++

#include <iostream>
#include <time.h>
#include <list>
using namespace std;
void PareY();
void PareA();
void PareB();
void PareE();
static list<string> s;
void showlist(list<string> g)
{
list<string>::iterator it;
for (it = g.begin(); it != g.end(); ++it)
cout << ' ' << *it;
cout << '\n';
}
int main() {
time_t t;
srand((unsigned) time(&t));
cout << "<E>::=(<Y>)" << endl;
cout << "<Y>::=<A><B>" << endl;
cout << "<A>::=ν|<Ε>" << endl;
cout << "<Β>::=-<Υ>|+<Υ>|ε" << endl;
PareE();
cout << "---------------" << endl;
showlist(s);
return 0;
}
void PareE(){
cout << "E -> (Y)" << endl;
s.push_back("(");
PareY();
s.push_back(")");
}
void PareY(){
cout << "Y -> AB" << endl;
PareA();
PareB();
}
void PareA(){
if((rand() % 2 ) == 0){
cout << "A -> ν" << endl;
s.push_back("ν");
}else{
cout << "A -> E" << endl;
PareE();
}
}
void PareB(){
if((rand() % 3) == 0){
cout << "B -> -Y" << endl;
s.push_back("-");
PareY();
}
else if((rand() % 3) == 1){
cout << "B -> +Y" << endl;
s.push_back("+");
PareY();
}else{
cout << "B -> ε" << endl;
}
}
I have to create strings based on the grammar seen in the couts in the main function.
When i run tests, it sometimes prints stuff nonstop (it only stops if i hit the stop) why is that?
I have to show the steps as well e.x E -> (Y) -> (AB) -> (νB) -> (ν-Y) -> (ν-(ΑΒ)) and so on instead of what i've done (i'm just showing the production rule) and i don't know how to do that. I'm using a list there just for the outcome but should i use a list as well for the production? I don't know how else to do it.
<E>::=(<Y>)
<Y>::=<A><B>
<A>::=ν|<Ε>
<Β>::=-<Υ>|+<Υ>|ε
E -> (Y)
Y -> AB
A -> ν
B -> ε
---------------
( ν )
That's an example. It should be something like E -> (Y) -> (AB) -> (νΒ) -> (ν). The only thing i can think of is having a list storing the current string..

The grammar has recursions. That is the reason, why it may continue long.
For example can call again recursivly. And so on and so on. Depending on the random number. In it will quite often happen that it runs until stack overflow :-) The grammar is rather explosiv...
And if we show the states in a recursive decent way, we can just output the state in the nonterminal function. But I am not sure if that is what you want. I put the characters of the string in a vector. But, whatver container is ok.
The only terminals that you have are 'v', '+' and '-'.
#include <iostream>
#include <time.h>
#include <vector>
using namespace std;
void PareY();
void PareA();
void PareB();
void PareE();
vector<vector<char>> strings{};;
int main() {
strings.push_back({});
time_t t;
srand((unsigned)time(&t));
cout << "<E>::=(<Y>)" << endl;
cout << "<Y>::=<A><B>" << endl;
cout << "<A>::=ν|<Ε>" << endl;
cout << "<Β>::=-<Υ>|+<Υ>|epsilon" << endl;
cout << "\n\n---------------\n\nStart ";
PareE();
cout << "---------------\n\nStrings:\n\n" << endl;
for (const auto& s : strings) {
for (const char c : s) std::cout << c;
std::cout << '\n';
}
return 0;
}
void PareE() {
cout << " -> (E)";
PareY();
}
void PareY() {
cout << " -> (Y)";
PareA();
PareB();
}
void PareYPlus() {
cout << " -> +(Y)";
PareA();
PareB();
}
void PareYMinus() {
cout << " -> -(Y)";
PareA();
PareB();
}
void PareA() {
cout << " -> (A)";
if ((rand() % 2) == 0) {
cout << " -> v";
strings.back().push_back('v');
}
else {
PareE();
}
}
Potential output:
<E>::=(<Y>)
<Y>::=<A><B>
<A>::=ν|<Ε>
<Β>::=-<Υ>|+<Υ>|epsilon
---------------
Start -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> (E) -> (Y) -> (A) -> (E) -> (Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon -> (B) -> -(Y) -> (A) -> v -> (B) -> -(Y) -> (A) -> v -> (B) -> +(Y) -> (A) -> v -> (B) -> epsilon -> (B) -> epsilon---------------
Strings:
v-v-v+v
-v
-v-v+v+v
+v+v+v
+v-v
-v-v-v+v
-v-v
-v-v+v
+v-v-v+v
+v
-v-v-v
-v-v
-v-v+v+v-v+v+v-v

Related

Convert GeoPackage to GeoJSON with ogr2ogr not working

The command
ogr2ogr -f GeoJSON out.json BGRI2021_0706.gpkg
returns
ERROR 1: database disk image is malformed
FAILURE:
Unable to open datasource `BGRI2021_0706.gpkg' with the following drivers.
-> `FITS'
-> `PCIDSK'
-> `netCDF'
-> `PDS4'
-> `VICAR'
-> `JP2OpenJPEG'
-> `PDF'
-> `MBTiles'
-> `BAG'
-> `EEDA'
-> `OGCAPI'
-> `ESRI Shapefile'
-> `MapInfo File'
-> `UK .NTF'
-> `LVBAG'
-> `OGR_SDTS'
-> `S57'
-> `DGN'
-> `OGR_VRT'
-> `REC'
-> `Memory'
-> `CSV'
-> `NAS'
-> `GML'
-> `GPX'
-> `LIBKML'
-> `KML'
-> `GeoJSON'
-> `GeoJSONSeq'
-> `ESRIJSON'
-> `TopoJSON'
-> `Interlis 1'
-> `Interlis 2'
-> `OGR_GMT'
-> `GPKG'
-> `SQLite'
-> `ODBC'
-> `WAsP'
-> `PGeo'
-> `MSSQLSpatial'
-> `OGR_OGDI'
-> `PostgreSQL'
-> `MySQL'
-> `OpenFileGDB'
-> `DXF'
-> `CAD'
-> `FlatGeobuf'
-> `Geoconcept'
-> `GeoRSS'
-> `GPSTrackMaker'
-> `VFK'
-> `PGDUMP'
-> `OSM'
-> `GPSBabel'
-> `OGR_PDS'
-> `WFS'
-> `OAPIF'
-> `SOSI'
-> `Geomedia'
-> `EDIGEO'
-> `SVG'
-> `CouchDB'
-> `Cloudant'
-> `Idrisi'
-> `ARCGEN'
-> `XLS'
-> `ODS'
-> `XLSX'
-> `Elasticsearch'
-> `Walk'
-> `Carto'
-> `AmigoCloud'
-> `SXF'
-> `Selafin'
-> `JML'
-> `PLSCENES'
-> `CSW'
-> `VDV'
-> `GMLAS'
-> `MVT'
-> `NGW'
-> `MapML'
-> `TIGER'
-> `AVCBin'
-> `AVCE00'
-> `HTTP'
I am in the correct directory and the file exists
ll BGRI2021_0706.gpkg -h
-rw-r--r-- 1 joao joao 1,1M nov 28 18:07 BGRI2021_0706.gpkg
ogr2ogr support the format:
$ ogrinfo --formats | grep GPKG
GPKG -raster,vector- (rw+vs): GeoPackage
I am using v3.3.2
$ ogr2ogr --version
GDAL 3.3.2, released 2021/09/01

Please explain the ppx_variants_conv make_matcher method signature

I found myself wanting a way to do some codegen around some large variant types in my code, and I found ppx_variants_conv (https://github.com/janestreet/ppx_variants_conv)
The make_matcher method sounds potentially useful to me, but there are no docs and tbh I am struggling to read the example signature:
val make_matcher :
a:(('a -> 'a t) Variant.t -> 'b -> ('c -> 'd) * 'e)
-> b:((char -> 'f t) Variant.t -> 'e -> (char -> 'd) * 'g)
-> c:('h t Variant.t -> 'g -> (unit -> 'd) * 'i)
-> d:((int -> int -> 'j t) Variant.t -> 'i -> (int -> int -> 'd) * 'k)
-> 'b
-> ('c t -> 'd) * 'k
a b c and d labelled arguments correspond to the cases of the variant and the first part of each signature corresponds to the constructor for each case... I get a bit lost after that 🤔
and it seems a odd to me that 'b 'c 'd and 'k appear in the latter part of the signature but not 'e 'f 'g 'h 'i 'j
In the make_matcher function each labeled argument takes a function of two arguments that has a general form, fun v x -> f, y, where v is the first-class variant that represents the corresponding constructor, x is the value that is folded over all matchers-generating functions. The function returns a pair, in which the first constituent, the function f, is actually the matcher that will be called if that variant matches and some value y that will be passed to the next matcher-generating function.
Let's do some examples to illustrate this. First, let's define some simple matcher, e.g.,
type 'a t =
| A of 'a
| B of char
| C
| D of int * int
[##deriving variants]
let matcher init = Variants.make_matcher
~a:(fun v (x1 : char) ->
(fun x -> x+1),Char.code x1)
~b:(fun v (x2 : int) ->
(fun c -> Char.code c),float x2)
~c:(fun v (x3 : float) ->
(fun () -> 0), string_of_float x3)
~d:(fun v (x4 : string) ->
(fun x y -> x + y),[x4])
init
and here's how we can use, it,
# let f,s = matcher '*';;
val f : int t -> int = <fun>
val s : Base.string list = ["42."]
# f (A 10);;
- : int = 11
# f (B '*');;
- : int = 42
# f C;;
- : int = 0
# f (D (1,2));;
- : int = 3
To be honest, I don't know the purpose of the extra parameter that is passed to each matcher-generating function1. Probably, the idea is that depending on the initial parameter we could generate different matchers. But if you don't need this, then just pass () to it and/or define your own simplified matcher that ignores this additional information, e.g.,
let make_simple_matcher ~a ~b ~c ~d =
fst ##Variants.make_matcher
~a:(fun _ _ -> a,())
~b:(fun _ _ -> b,())
~c:(fun _ _ -> c,())
~d:(fun _ _ -> d,())
()
The make_simple_matcher function has an expected type,
a:('a -> 'b) ->
b:(char -> 'b) ->
c:(unit -> 'b) ->
d:(int -> int -> 'b) ->
'a t -> 'b
1) looking into the guts of the code that generates this function doesn't help a lot, as they use the generic name acc for this parameter, which is not very helpful.

Does OCaml's type system prevent it from modeling Church numerals?

As a pass-time, I'm trying to implement all kinds of problems that were presented in a course (concerned with Lambda Calculus and various programming concepts) I took at the university. So, I'm trying to implement Church numerals and associated operators in OCaml (also as an exercise in OCaml).
This is the code so far:
let church_to_int n =
n (fun x -> x + 1) 0;;
let succ n s z =
s (n s z)
let zero = fun s z -> z
let int_to_church i =
let rec compounder i cont =
match i with
| 0 -> cont zero
| _ -> compounder (i - 1) (fun res -> cont (succ res))
in
compounder i (fun x -> x)
let add a b = (b succ) a
let mul a b = (b (add a)) zero
So, it seems to work, but then it breaks down. Let's consider these definitions:
let three = int_to_church 3
let four = int_to_church 4
church_to_int (add three four) // evaluates to 7
church_to_int (add four three) // throws type error - see later
I get that the error thrown has to do with the type polymorphism of the Church numerals when they're defined (see SO question), and then it's resolved after the closures are invoked once. However, I don't seem to understand why the type inconsistency error is thrown in this case:
let three = int_to_church 3
let four = int_to_church 4
church_to_int (mul three four) // throws type error - see later
Any thoughts?
The specific errors:
1.
Error: This expression has type (int -> int) -> int -> int but an expression was expected of type ((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
((((int -> int) -> int -> int) -> (int -> int) -> int -> int) ->
((int -> int) -> int -> int) -> (int -> int) -> int -> int) ->
'd
Type int is not compatible with type ('a -> 'b) -> 'c -> 'a
2.
Error: This expression has type ((((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) -> (('d -> 'd) -> 'd -> 'd) -> 'e) ->
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
(((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e
but an expression was expected of type
((((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e) ->
'e) ->
('f -> 'g -> 'g) -> 'h
The type variable 'e occurs inside
((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) ->
(('d -> 'd) -> 'd -> 'd) -> 'e
Well i was a bit rusty with lambda-calculus, but after few discussions with some wise old men, i came to this answer : YES, writing that way, OCaml's type system do not allow the writing of Church numerals.
The real problem here is with your addition term :
let add a b = b succ a
wich has the following type
(((('a -> 'b) -> 'c -> 'a) -> ('a -> 'b) -> 'c -> 'b) -> 'd -> 'e) -> 'd -> 'e
Where the arguments of add have not the same type. This is a bit sad since we naively expect the addition to be commutative.
You can easily verify this when writing :
let double a = add a a (* produces type error - the type variable occurs ... *)
This error means that you're trying to unify one type with a "bigger" type i.e that contains it (ex: unifying 'a with 'a -> 'a). OCaml does not allow that (unless if you set the -rectypes option wich allows cyclic types).
To understand better what's going on, let's add type annotations to help the typer (i'll change a bit your notations for sake of clarity):
type 'a church = ('a -> 'a) -> 'a -> 'a
let zero : 'a church = fun f x -> x
let succ n : 'a church = fun f x -> f (n f x)
Now let's go back to the add term and annotate it a bit to see what the typer has to say:
let add (a:'a church) b = a succ b (* we only annotate "a" to let the typer infer the rest *)
This produces a very odd type :
'a church church -> 'a church -> 'a church
That gets interesting: why is the first arg typed as an 'a church church?
The answer is the following : Here, a church integer is a value that takes a moving function of type 'a -> 'a (a self-map in mlahematics) that can browse a space, and an starting point ('a) that belongs to that space.
Here, if we specify that the parameter a has type 'a church, than 'a represent the space in which we can move.
Since succ, the moving function of a, operates over the church, than 'a here is it self an 'a church, thus making the parameter a an 'a church church.
This is not at all the type we wanted at the begining ... but that justifies why the type system do not allow your values three and four as both 1st and snd argument of add.
One solution can be to write add in a different way :
let add a b f x = a f (b f x)
Here, both a and b have the same moving function, and thus the same type, but you do not enjoy anymore the beautiful writing with the partial application ...
An other solution which makes you keep this beautiful writing would be to use universal types, that allow a larger kind of polymorphism:
type nat = {f:'a.('a -> 'a) -> 'a -> 'a}
(* this means “for all types ‘a” *)
let zero : nat = {
f=fun f x -> x
}
let succ n : nat = {
f= fun f x -> f (n.f f x)
}
let add (a:nat) (b:nat) = a.f succ b
let double a = add a a (* Now this has a correct type *)
let nat_to_int n =
n.f (fun x -> x + 1) 0;;
let nat_four = succ (succ (succ (succ zero)))
let eight_i = double nat_four |> nat_to_int //returns 8
But this solution is a bit more verbose than your initial one.
Hope it was clear.
If you look at the type of three, you get that:
val three : ('_a -> '_a) -> '_a -> '_a = <fun>
This is simply the value restriction at work. The value restriction is well explained here: https://realworldocaml.org/v1/en/html/imperative-programming-1.html#side-effects-and-weak-polymorphism
To solve it, In this case you can simply eta-expand the function:
let three x = int_to_church 3 x ;;
val three : ('a -> 'a) -> 'a -> 'a = <fun>

Hint for SML type inference

I am new to SML and I am trying to practice in SML type reference.I am trying to deduct the below types:
a)fun add42 x =x+42
b)fun comp F G = let fun C x = G(F(x)) in C end
c)fun compA42 x = comp add42 x
d)val foo = compA42 add42
e)fun compCompA42 x = comp compA42 x
I think the solutions for the first four is:
a)int->int
b)(a->b)->(b->c)->a->c
c)(int->a)->int->a
d)int->int
But I am a little bit confused about the last one.
Is there any hint to deduct the last type??
Thanks a lot.
Let's do this manually, step-by-step:
fun compCompA42 x = comp compA42 x
It's a function, so compCompA42 has type α -> β.
compCompA42's return value must be of the same type as comp compA42 x, i.e. β = typeof(comp compA42 x).
We already now the most general type for comp:
(a -> b) -> (b -> c) -> a -> c
Now, we need to specialize it for the case when a -> b = typeof(compA42) and (b -> c) = α:
a -> b = typeof(compA42) = (int -> d) -> int -> d. From this equation follows that a = int -> d and b = int -> d.
So, α = b -> c = (int -> d) -> c and β = typeof(comp compA42 x) = a -> c = (int -> d) -> c.
Finally, our most general type for compCompA42 is
α -> β = ((int -> d) -> c) -> (int -> d) -> c.
Observe that you can always make some SML interpreter (e.g., smlnj) show you types:
- fun compCompA42 x = comp compA42 x;
val compCompA42 = fn : ((int -> 'a) -> 'b) -> (int -> 'a) -> 'b
And it's the same type we've got manually (just rename d to 'a and c to 'b).

Ocaml's named parameters

Trying to understand Ocaml's mechanism for named parameters. I understand the basics, but the doc shows an example like this:
# let f ~x ~y = x - y;;
val f : x:int -> y:int -> int = <fun>
# let x = 3 and y = 2 in f ~x ~y;;
- : int = 1
What exactly is going on when only the tilde is used in application? Is it just shorthand for ~x:x, similar to definitions? If so, can someone explain why this:
# ListLabels.fold_left;;
- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
# let add = (+) and i = 0
in ListLabels.fold_left ~add ~i [1;2;3];;
produces
- : f:((add:(int -> int -> int) -> i:int -> 'a) ->
int -> add:(int -> int -> int) -> i:int -> 'a) ->
init:(add:(int -> int -> int) -> i:int -> 'a) -> 'a = <fun>
The man says
"beware that functions like ListLabels.fold_left whose result type is a type variable will never be considered as totally applied."
Here is what happens in your example. Beware it's a bit involved.
# ListLabels.fold_left;;
- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
is just the classic use: ListLabels.fold_left taks 3 arguments, namely a function labeled f, an initializer init and a list.
Now, in
let add = (+) and i = 0
in ListLabels.fold_left ~add ~i [1;2;3];;
the application ListLabels.fold_left ~add ~i [1;2;3] is considered incomplete (as the man says). That means that `ListLabels.fold_left receives first its unamed argument, [1;2;3] and returns a function of type f:('a -> int -> 'a) -> init:'a -> 'a. Let us call this function foo.
Since you're giving two named arguments, labeled add and i, the type 'a is inferred to be a functional type, of type add:'c -> ~i:'d -> 'e.
Based on the type of the variables add and i, the type 'c must be int -> int -> int, and 'd must be int.
Replacing those values in the type 'a, we derive that the type 'a is add:(int -> int -> int) -> i:int -> 'e.
And replacing this in the type of foo (I'm glad there is copy-pasting ;-), its type is
f:((add:(int -> int -> int) -> i:int -> 'e)
-> int
-> (add:(int -> int -> int) -> i:int -> 'e))
-> init:(add:(int -> int -> int) -> i:int -> 'e)
-> (add:(int -> int -> int) -> i:int -> 'e)
Removing unecessary parentheses, and alpha converting (i.e. renaming) 'e to 'a, we get
f:((add:(int -> int -> int) -> i:int -> 'a)
-> int
-> add:(int -> int -> int) -> i:int -> 'a)
-> init:(add:(int -> int -> int) -> i:int -> 'a)
-> add:(int -> int -> int) -> i:int -> 'a
That is the type of foo. But remember that you are passing two arguments to foo, labeled ~add and ~i. So the value you get at the end is not of type add:(int -> int -> int) -> i:int -> 'a but indeed of type 'a. And the whole type of your example is, as returned by the compiler,
f:((add:(int -> int -> int) -> i:int -> 'a)
-> int
-> add:(int -> int -> int) -> i:int -> 'a)
-> init:(add:(int -> int -> int) -> i:int -> 'a)
-> 'a