Check whether an input is real of integer - sml

I want to ask the user to input a variable and check it is real or integer and take two different operations for corresponding actions. Say true if integer else false;
fun realorinteger(n)= if n=int then true else false;
but it definitely does not work. I tried if n in int as well.
Any help?

You cannot do this.
The type system simply doesn't allow a function to take multiple different types, and act according to which type it is. Either your function takes an int, or it takes a real. (Or it takes both, but can also take strings, lists, etc... ie. is polymorphic)
You could fake it by making a datatype, which encapsulates values that can be either integers or reals, like so:
datatype intorreal = IVal of int | RVal of real
You can then use pattern matching on such a value to extract the desired number:
fun realorinteger (IVal i) = ... (* integer case here *)
| realorinteger (RVal r) = ... (* real case here *)
This function will then have the type intorreal -> x, where x is the type of the right-hand-side expressions. Note, the resulting value must be of the same type in both cases.
An example of such a function could be a rounding function:
fun round (IVal i) = i
| round (RVal r) = Real.round r
Which is then called like so:
val roundedInt = round (IVal 6);
val roundedReal = round (RVal 87.2);

Related

How do I compare values for equality by Type Constructor?

Background
I'm a relative newcomer to Reason, and have been pleasantly suprised by how easy it is to compare variants that take parameters:
type t = Header | Int(int) | String(string) | Ints(list(int)) | Strings(list(string)) | Footer;
Comparing different variants is nice and predictable:
/* not equal */
Header == Footer
Int(1) == Footer
Int(1) == Int(2)
/* equal */
Int(1) == Int(1)
This even works for complex types:
/* equal */
Strings(["Hello", "World"]) == Strings(["Hello", "World"])
/* not equal */
Strings(["Hello", "World"]) == Strings(["a", "b"])
Question
Is it possible to compare the Type Constructor only, either through an existing built-in operator/function I've not been able to find, or some other language construct?
let a = String("a");
let b = String("b");
/* not equal */
a == b
/* for sake of argument, I want to consider all `String(_)` equal, but how? */
It is possible by inspecting the internal representation of the values, but I wouldn't recommend doing so as it's rather fragile and I'm not sure what guarantees are made across compiler versions and various back-ends for internals such as these. Instead I'd suggest either writing hand-built functions, or using some ppx to generate the same kind of code you'd write by hand.
But that's no fun, so all that being said, this should do what you want, using the scarcely documented Obj module:
let equal_tag = (a: 'a, b: 'a) => {
let a = Obj.repr(a);
let b = Obj.repr(b);
switch (Obj.is_block(a), Obj.is_block(b)) {
| (true, true) => Obj.tag(a) == Obj.tag(b)
| (false, false) => a == b
| _ => false
};
};
where
equal_tag(Header, Footer) == false;
equal_tag(Header, Int(1)) == false;
equal_tag(String("a"), String("b")) == true;
equal_tag(Int(0), Int(0)) == true;
To understand how this function works you need to understand how OCaml represents values internally. This is described in the section on Representation of OCaml data types in the OCaml manual's chapter on Interfacing C with OCaml (and already here we see indications that this might not hold for the various JavaScript back-ends, for example, although I believe it does for now at least. I've tested this with BuckleScript/rescript, and js_of_ocaml tends to follow internals closer.)
Specifically, this section says the following about the representation of variants:
type t =
| A (* First constant constructor -> integer "Val_int(0)" *)
| B of string (* First non-constant constructor -> block with tag 0 *)
| C (* Second constant constructor -> integer "Val_int(1)" *)
| D of bool (* Second non-constant constructor -> block with tag 1 *)
| E of t * t (* Third non-constant constructor -> block with tag 2 *)
That is, constructors without a payload are represented directly as integers, while those with payloads are represented as "block"s with tags. Also note that block and non-block tags are independent, so we can't first extract some "universal" tag value from the values that we then compare. Instead we have to check whether they're both blocks or not, and then compare their tags.
Finally, note that while this function will accept values of any type, it is written only with variants in mind. Comparing values of other types is likely to yield unexpected results. That's another good reason to not use this.

ABAP equality check is wrong for INT4 and CHAR numeric

I've ran into an issue here, and I can't figure out exactly what SAP is doing. The test is quite simple, I have two variables that are a completely different type as well as having two completely different values.
The input is an INT4 of value 23579235. I am testing the equality function against a string '23579235.43'. Obviously my expectation is that these two variables are different because not only are they not the same type of variable, but they don't have the same value. Nothing about them is similar, actually.
EXPECTED1 23579235.43 C(11) \TYPE=%_T00006S00000000O0000000302
INDEX1 23579235 I(4) \TYPE=INT4
However, cl_abap_unit_assert=>assert_equals returns that these two values are identical. I started debugging and noticed the 'EQ' statement was used to check the values, and running the same statement in a simple ABAP also returns 'true' for this comparison.
What is happening here, and why doesn't the check fail immediately after noticing that the two data types aren't even the same? Is this a mistake on my part, or are these assert classes just incorrect?
report ztest.
if ( '23579235.43' eq 23579235 ).
write: / 'This shouldn''t be shown'.
endif.
As #dirk said, ABAP implicitly converts compared or assigned variables/literals if they have different types.
First, ABAP decides that the C-type literal is to be converted into type I so that it can be compared to the other I literal, and not the opposite because there's this priority rule when you compare types C and I : https://help.sap.com/http.svc/rc/abapdocu_752_index_htm/7.52/en-US/abenlogexp_numeric.htm###ITOC##ABENLOGEXP_NUMERIC_2
| decfloat16, decfloat34 | f | p | int8 | i, s, b |
.--------------|------------------------|---|---|------|---------|
| string, c, n | decfloat34 | f | p | int8 | i |
(intersection of "c" and "i" -> bottom rightmost "i")
Then, ABAP converts the C-type variable into I type for doing the comparison, using the adequate rules given at https://help.sap.com/http.svc/rc/abapdocu_752_index_htm/7.52/en-US/abenconversion_type_c.htm###ITOC##ABENCONVERSION_TYPE_C_1 :
Source Field Type c -> Numeric Target Fields -> Target :
"The source field must contain a number in mathematical or
commercial notation. [...] Decimal places are rounded commercially
to integer values. [...]"
Workarounds so that 23579235.43 is not implicitly rounded to 23579235 and so the comparison will work as expected :
either IF +'23579235.43' = 23579235. (the + makes it an expression i.e. it corresponds to 0 + '23579235.43' which becomes a big Packed type with decimals, because of another rule named "calculation type")
or IF conv decfloat16( '23579235.43' ) = 23579235. (decfloats 16 and 34 are big numbers with decimals)

Is there any significance to this return statement?

I was wondering if there was any significance in a part of a code I am seeing that involves
return (num!=0);
where num is an int. And this is the return statement of a boolean function that wants to return TRUE if num != 0, and false if num = 0.
I am not sure if there is an hidden significance to this, but I am not seeing why they cannot just simply write:
return num;
Here is the code I saw:
bool SemClass::cut(int &a, int &b, int &c)
{
int num = 0;
check(a, num);
check(b, num );
check(c, num);
return (num != 0);
}
The value 0 for integral, floating-point, and unscoped enumeration and the null pointer and the null pointer-to-member values become false when returned as a boolean by implicit conversion. Other values such as 1, 2, 3, 4 etc. map to true. This convention was established in original C, via its flow control statements; C didn't have a boolean type at the time.
Implicit conversions: en.cppreference.com/w/cpp/language/implicit_cast
In this case, in C++, writing num and num!=0 are both fine. However, num!=0 might make it more obvious that the method is returning a boolean. Technically, only an integer of value 0 would equate to a boolean false, while all other values would equate to a boolean true. By writing num!=0, It is made explicit that the method would return true if num is not equivalent to 0 and false if it is.
Good practice dictates that if it's a genuine truth value, then you should use a boolean as it makes it very clear to the caller what will be returned. When returning an integer, it could be seen as a code/enum type value.
Therefore, num!= is preferred to num in this case. The brackets are not required however. Some compilers will also issue a warning if you return an integer when the method is supposed to return a boolean.
The author may have written return num, the compiler would generate the exact same binary. Here, the author tries to be explicit and to make as easy as possible to the reader to guess what the function returns.
When a quick reader sees return num knowing that num is an int and the current function returns a bool, (s)he needs to stop for a fraction of a second to a few seconds (depending on its concentration and ease regarding C++) to remember that an integer is implicitly convertible to a boolean with the mapping 0 -> false, anything else -> true. So, why not write that down?
When the quick reader sees return num!=0, (s)he guesses that the current function returns a boolean (it could be otherwise, but it would be suspicious) and comprehend easily what the return value means.
As a rule of thumb, I'd advise to pick the more explicit writing when it does not hurt the reading and when it takes only a few more (or less) characters. Don't forget that you do not write code for the compiler, you write code for the dozens of other developers who works or will work with you(r code). C++ may be less common in 20 years, it would be great if your program could be easily understood not only by gurus but by everyone (I'm generalizing there, not only talking about the implicit boolean conversion).
The author is being (excessively) careful on two counts:
The parentheses are redundant.
Any numeric type in C++ has an implicit conversion to bool: if the number compares to zero then it's false, else it's true.
Personally I prefer the naked return num; as I find that clearer.
(Note that in C, the relational operators return the int types 1 and 0, rather than true and false).

Can't understand error in this program for checking automorphic no.?

int a = 0, b, c, e, n = 25;
e = n;
while(n!=0)
{
n=n/10;
a++;
}
printf("%d",a);
b = e * e;
c = b % (pow(10, a));
if(c==e)
printf("automorphic");
For the line
c=b%(pow(10,a));
the compiler shows an error:
invalid operands of types `int' and `double' to binary `operator%'
pow returns a double, and you can't use % on doubles.
pow returns a double, which you cannot use as operator for the %.
Try:
c=b%((int)pow(10,a));
instead.
As per other answers: pow introduces doubles into your program, and then you hvave to convert them back to ints.
Best to avoid the problem, then:
int a = 1;
while(n!=0)
{
n=n/10;
a *= 10;
}
a /= 10;
b=e*e;
c=b%a;
(Edit) I marked a line "Fishy" because what happens with n=0..9? You probably need
while (n >= 10)
..
(Edit again, sigh) Sorry -- above edit is wrong, you need the total number of digits. a needs adjusting after the loop.
The % operator can be operated only with integers. pow function returns a double and that's why you are getting error.
In C/C++ the modulus operator (%) is limited to integers. You can use fmod (...) for floating-point modulus but you still need to match types to use that. So you are going to have to cast one of your variables or expressions no matter which solution you chose to use; I would use integer modulus personally.
This is in contrast to languages like Java and C#, which allow you to have an integer on one side of the modulus operator and a float on the other with no problems. This can be a source of portability headaches when porting from other languages into C.
The code can be corrected as:
int a = 0, b, c, e, n = 25;
e = n;
while(n!=0)
{
n=n/10;
a++;
}
printf("%d",a);
b = e * e;
/*
call to pow() function returns a double value and b is an integer type variable.
For any operation (here, modular division) the operands must be of same type.
So, the double value returned from call to pow() function must be explicitly
casted to int type as shown in the code below. Also, the first argument to pow()
must to be double (or, float) type. Here, 10 is integer type, correct it as 10.0.
The result will be fine.
*/
c = b % (int)(pow(10.0, a));
if(c==e)
printf("automorphic");

I get datatype, but what is the point of defining types in sml?

It seems like defining types in SML isnt that helpful:
type point = int * int
val origin : point = (0, 0)
But I could easily just use int * int for typing methods, no? Compared with datatype, with which it seems you can do more interesting things like:
datatype Point = PlanePoint of (int * int) | SpacePoint of (int * int * int)
val origin : Point = SpacePoint(0, 0, 0)
Out of curiosity, what are situations where you really just gotta have a type defined?
The reason is mostly type safety. I will try to explain with a simple example.
Say you have a module that uses 2 types that are represented with real * real
For example, a 2d point like in your example, and a line represented by a slope and a y intercept. Now if you're writing a function like lies_on_line which takes a a point and a line and returns a boolean whether the point lies on the line you have 2 choices for a signature:
val lies_on_line : (int * int) * (int * int) -> bool
Ord
val lies_on_line : point * line -> bool
It's obvious that the 2nd example makes it harder to make mistakes.
Also, while it's more of a benefit for modules, naming a type allows you to change its representation without changing code that uses the type (indirectly through the module).
It makes sense to define aliases for your types in the context of your problem domain. That way you can think in your design in terms of more relevant and meaningful types.
For instance if you are writing a word processor program then you have types like:
type Word = string
type Sentence = Word list
which may make more sense than string and string list.