What does (int -> int) mean? - sml

I'm trying to decipher the meaning of the type choice part of this. From what I can gather, it's multiplying an int, by (int -> int), by another int. I'm just confused as to what (int -> int) means. Any help would be much appreciated.
val callcc = SMLofNJ.Cont.callcc
val throw = SMLofNJ.Cont.throw
type 'a cont = 'a SMLofNJ.Cont.cont
type choice = int cont * (int -> int) * int

( int -> int ) means a function that takes 1 int argument and returns an int. What you are defining is not a multiplication. 'choice' is a type defined as a 3-tuple. The 3-tuple consist of an int, a function that takes an int and returns an int, and finally another int.

Let me start by clarifying some things that I think you've misunderstood:
type choice = ... is declaring choice as a "type constructor", meaning that it denotes a type rather than a value. The right-hand-side is then a "type expression"; for example, you could write type myInt = int to declare myInt as an alternative name for the int type.
int * int, in a type expression, doesn't mean "an int times an int"; rather, it denotes the type "pair of int-s". For example, the value expression (1, 2) has type int * int.
That out of the way . . . int -> int denotes the type "function that takes an int and returns an int". For example, the value expression fn i => 2 * i, which is a function that takes an integer and returns double that integer, has type int -> int.
Putting this together,
type choice = int cont * (int -> int) * int
declares choice to mean "a triple (3-tuple) whose first element is an int cont; whose second element is a function that takes an int and returns an int; and whose third element is an int".

Related

How C++ understands Array as pointers point of view?

I wrote the piece of code below but when I tried to return some two-dimensional array, it throws the following error.
int (* function (int input[2][2]) ) [2][2]{
return input;
}
from trial and error, I understand that when I change the function declaration to int (* function (args) ) [2] {...} it works like a charm, but why??? I don't understand. How C++ actually sees arrays? How these return declarations int (* function () )[n][m] actually works? What happens when I add another * to function declaration int *(* function () )[n][m] ??
My source for finding the solution to this problem was this but I just copied some code and understood almost 0% of it.
It'll be nice if someone could explain to me how these work, and it would mean a world to me if you can suggest a good reading source for understanding these somewhat advanced notions in C++.
In this function declaration
int (* function (int input[2][2]) ) [2][2];
the argument of the array type is implicitly adjusted by the compiler to pointer to the array element type. That is for example these function declarations
int (* function (int input[2][2]) ) [2][2];
int (* function (int input[100][2]) ) [2][2];
int (* function (int input[][2]) ) [2][2];
declares the same one function that is equivalent to
int (* function (int ( *input )[2]) ) [2][2];
So within the function the variable input has the pointer type int ( * )[2]. This pointer you are returning from the function
return input;
So the function return type also must be int ( * )[2]. That means that the function must be declared like
int (* function (int input[2][2]) ) [2];
You could declare the parameter as having a referenced type. In this case you may return reference to the array.
int ( & function (int ( &input )[2][2]) )[2] [2];
Array types may not be used as the return type of function.
As for this declaration
int *(* function () )[n][m];
where n and m shall be constant expressions then the function returns pointer of the type int * ( * )[n][m]. For example the function can use an array name declared within the function with the static storage duration something in a return statement like
static int * a[k][n][m];
//
return a;
So if you have an array as for example
T a[N1][N2][N3];
where T is some type and N1, N2, and N3 its sizes then this declaration you may rewrite like
T ( a[N1] )[N2][N3];
Used in expressions the array (with rare exceptions) is converted to pointer to its first element. To declare such a pointer substitute the record in the parentheses to pointer like
T ( *p )[N2][N3] = a;

Purpose of using (int) in the code below?

n=b.size()
n = max(n,(int)a.size());
where a and b are some user-Input strings and n is an integer. would anybody tell me why we use (int)a.size() and what is the purpose of using (int).
I am assuming that n is of type int, and your program will be something like this :
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string a ("Test string");
string b ("Test two");
int n = b.size() ;
n = max(n,(int)a.size());
cout << "n : " << n ;
return 0;
}
Now if you see the documentation for the .size() method of the string class, you will see it returns value of type : size_t
size_t is an unsigned integral type (the same as member type
string::size_type)
: as per documentation
Now when we look at the documentation for max() you can see it uses templating (you can read more about templating here) what it essentially means is that you can use any type as parameter (int, float, etc..) but both the parameters need to be the same type.
Now since n was declared as an int when calling max(n,x);, x needs to be type of n which basically means int in our case.
Now this is the reason for using (int) before a.size(). What we are doing here is type casting, since a.size() returns in type size_t which is different from int (You can read more about this here), we need to typecast the return value to int which can be done by (int)a.size().
SIDE NOTE
int n = max(b.size(),a.size());
cout << "n : " << n << " \n";
would also work, since both are same type so no need to do type casting.

Musing about variable declaration and the typedef specifier in c++

If you want to declare an int you do for instance
int x;
You could after assign a value to x (or "define" x) for instance as follows :
x = 3;
Of course, you could have done directly
int x = 3;
There are types whose variables should be declared and defined at the same time, for instance
const double y = 2.3;
as well as type whose variables you simply can't declare and define at the same time, for instance a pointer to an array of three char's :
typedef char (*pc3)[3];
char c3[3] = "ok";
pc3 apc3 = &c3;
(Am I wrong on the two previous examples ? Is there a one-liner (only one semi-column allowed) for the last one ?)
Consider now the following function pointer definition :
typedef int (*ipfunci)(int);
ipfunci fptr = &f; // where f is some int -> int function
(no one-liner for this as far as I know). Perfectly legal of course, but what about
typedef int (ifunci)(int);
Perfectly legal as well, but you can't define a variable of "type" 'ifunci' after having declared it, and what's it's use ?
This boils down to my real question : looking at
typedef char (*pc3)[3];
typedef int (*ipfunci)(int);
one sees an analogy between the two definitions, if one decides to see a size 3 array of char's as a function
0 -> char
1 -> char
2 -> char
One could also see
typedef int * pi ;
as the definition of the "type" pi as constant function with value equal to an int.
How far does this synthactic and functional analogy go ? What is behind types whose definitions really require a typedef : are they systematically "functional" types ?

Enum reference argument transfer instead of int reference argument

I have the following code :
typedef enum {Z,O,T} num;
bool toInt (str s,int& n);//<-if convert is possible converts s to integer ,puts the result in n and returns true,else returns false
I want to use toInt function and transfer as a second argument ,argument of type num
num n;
toInt("2",n);
This causes compilation error.
cannot convert parameter 2 from 'num' to 'int &'
I tried to use a cast : toInt("2",(num)n); But it is still problematic
How can I solve the issue?
A value of type num isn't an int, so it has to be converted to a temporary int before it is passed to the function. Tempories cannot be bound to a non-const reference.
If you want to convert via an int, you will have to convert in two steps:
int temp;
toInt("2", temp);
num n = static_cast<num>(temp);
I'd suggested, you add a new enum type for signaing invalid enum e.g:
enum num {Z,O,T,Invalid=4711} ;//no need to use typedef in C++
and change the signature to num instead of int:
bool toInt (str s, num& n)
{
if ( s=="Z" ) n=Z;
else if ( s=="O" ) n=O;
else if ( s=="T" ) n=T;
else { n=Invalid; return false; }
return true;
}
regards

Confusing type declaration?

I haven't worked with SML in awhile and I came across this line of code:
type memory = string -> int;
Does this define 'memory' to be a function which takes a string a returns an int, or something else entirely? I've searched for a similar declaration but I can't seem to find one or figure out what it does.
When I put it into SML/NJ, I just get this:
- type memory = string -> int;
type memory = string -> int
memory is not a function , it's just an abbreviation for a type that is a function that takes as input a string and returns an int.
So whenever you would like to write that something is of type string->int you can just write it's of type memory.
For example instead of writing:
- fun foo(f : string->int, s) = f s;
val foo = fn : (string -> int) * string -> int
you could write:
- fun foo( f: memory, s) = f s;
val foo = fn : memory * string -> int
Such type declarations can make your code more readable (e.g. instead of writing that a pair x is of type int*int like (x: int*int), you can just create an abbreviation type pair = int*int and then you can write that x is of type pair like this (x: pair)).