Now we will start talking about the points to note about the common handling operations for data types introduced in the previous article. However, before starting with detailed examples, I still want to re-list the names of the data types here so that we can easily follow the logic circuit and the relationship between the types (if any) –
Float
,Int
,number
– arithmetic values. For example:10.01
,10
, …Bool
– logical identifiersTrue
andFalse
Char
– single characters. For example:'A'
,'z'
, …String
– text strings. Example:"Elm Language"
Record
– describe records similar toC struct
andJS Object
Tuple
– concise description of records without field namesList
– stores values of the same type in the form of an enumeration list
Ok.. let’s get started. To save time, we will interact with Elm REPL
like the previous article. However, you can create module
files to save the example code if you want.
1 2 3 | cd Documents && cd learn-elm elm repl |
Arithmetic operations
Package:
elm/core/Basics
Not much different from Imperative
languages like C
or JavaScript
that we already know. +
, -
, *
, /
basic operations.
1 2 3 | 1.0 + 2.0 -- 3 : Float |
However, the first note is that Elm
does not support automatic conversion of the data type from Int
to Float
. The value returned by round
is of type Int
, and 1 : Int
cannot be added directly to 2.0 : Float
–
1 2 3 | (round 1.0) + 2.0 -- thông báo lỗi |
But 1 : number
and 2.0 : Float
are valid for such +
calculation. As for the reason, we will save it for the last item.
1 2 3 | 1 + 2.0 -- 3 : Float |
There is division to get the integer part with the //
symbol, I have never seen it.
1 2 3 | 9 // 2 -- 4 : Int |
The exponentiation uses the ^
notation, which is different from JS
‘s **
.
1 2 3 | 2 ^ 10 -- 1024 : number |
In addition, other operations will be handled by sub-program
. For example, division with remainder 9 % 2
in JS
–
1 2 3 | remainderBy 2 9 -- 1 : Int |
Taking the inverse of a number in Elm
will not use the -
operator. The reason is, I would like to save it for the next Sub-Series
. Here we just treat it as a special handling convention and use it like that.
1 2 3 | negate -9 -- 9 : number |
Absolute value –
1 2 3 4 5 6 | abs 10.01 -- 10.01 : Float abs -10.01 -- 10.01 : Float |
Square root of 2 –
1 2 3 | sqrt 81 -- 9 : Float |
Round the value to the nearest boundary –
1 2 3 4 5 6 | round 10.01 -- 10 : Int round 1.9 -- 2 : Int |
Round up and down –
1 2 3 4 5 6 | ceiling 9.5 -- 10 : Int floor 9.5 -- 9 : Int |
Decreasing to origin 0 –
1 2 3 4 5 6 | truncate 9.8 -- 9 : Int truncate -9.8 -- -9 : Int |
Checks the NaN
of a value obtained from an implementation that returns type Float
–
1 2 3 4 | isNaN (0/0) -- True isNaN (sqrt -1) -- True : Bool isNaN 1 -- False : Bool |
Division by 0/0
and taking the square root of -1
cannot give an arithmetically significant result, so we get the value NaN
. However, in the case below, the result is positive infinity. Infinite
is still of type Float
.
1 2 3 | isNaN (1/0) -- False : Bool |
and to check if a return value from a Float
type operation is Infinite
–
1 2 3 4 5 | isInfinite (0/0) -- False isInfinite (sqrt -1) -- False isInfinite (1/0) -- True isInfinite 1 -- False |
NaN
and Infinite
are fundamentally different: NaN
has no arithmetic meaning, and Infinite
is an arithmetic value.
Logical calculations
The symbols &&
and ||
used by Elm
with the same meaning as C
and JS
. However, negation, also known as the inverse of a Bool
value, is handled by the not
program, instead of the !
like C
and JS
.
1 2 3 4 5 6 | not True -- False : Bool not False -- True : Bool |
Comparative statements, most still use the notations as we know ==
, >
, <
, >=
, <=
. The only symbol !=
in C
and JS
to check the identity of two values is different, replaced by Elm
by /=
.
1 2 3 4 5 6 | 1 /= 0.9 -- True : Bool 1 /= 1.0 -- False : Bool |
Type Variable
Purely Declarative
languages are mostly built with one spirit in mind – very strong typing and strict strong-typing
. And here we have Elm
as one of them.
Specifically the error message like the +
calculation example between an Int
value and a Float
value that we saw at the beginning of the article. Although Elm
‘s compiler
already has enough information about the received values before performing the calculation, Elm
simply does not support automatic implicit type conversion in this case. And we will need to do the data type conversion in our code –
1 2 3 | (toFloat (round 1.0)) + 2.0 -- 3 : Float |
Oh but why does the calculation
1 + 2.0
have no error message?
The value 1
returned by round
is typed Int
. The value 1
that we write directly into our code file is untyped, so Elm
will treat it as a variable of type number
.
The concept of variable type Type Variable
, can be understood simply as any data type that the compiler
does not find explicit type information in the code. And will try to find a most suitable success processing logic when getting the actual value at code runtime
.
Precisely, a variable type a
is understood as a Union
type that includes all data types that the compiler collects in the definition code of the entire project
program. However, Elm
also generates a few Type Variable
with more limited possibilities than a
. That is –
number
– is an arithmetic value; So it can beFloat
orInt
.comparable
– is a value that can be compared by thecompare
program; IncludesInt
,Float
,Char
,String
, andList/Tupple
of those types.appendable
– is a value that can perform content concatenation operations; So it could be aString
or aList
.compappend
– is a value that is bothcomparable
andappendable
.
Thus, when the compiler reads the calculation 1 + 2.0
, the value 2.0
already has enough clear type information to be Float
due to the decimal point .
; The value 1
does not have specific type information, so it will be number
. The most suitable success logic is Float + Float
and we have the compiled logic as 1.0 + 2.0
. The calculation is done and there is no error message.
comparable
By the way, after introducing the concept of Type Variable
variable type, we have some predefined types as listed above. The number
we just used to illustrate the example above, and among the remaining types, here we have enough knowledge to talk about comparable
.
A value of type
comparable
can be used in a comparison operation using thecompare
program.
Here we need to pay a little attention to avoid confusion. The logical operations >
, <
, ==
, /=
, etc.. that return Bool
values are used to test a comparison statement. In other words, to test an evaluation. And such a kiểm tra
operation will have a slightly different meaning from the so sánh
compare
that we just talked about above.
A test a == b
will give the answer to the question: ” a
is equal to b
. True or False? If đúng
, choose True
, and if sai
, choose False
. !”
1 2 3 | 1 == 0.9 -- False : Bool |
And a compare ab
comparison, on the other hand, will give the answer to the question: “What is a
vs b
? Equal to EQ
? Or less than LT
? Or greater than GT
? Answer immediately and always !”
1 2 3 | compare 1 0.9 -- GT : Order |
The result of a so sánh
, then, of course can also be used to navigate the operating logic of the code we build. And Elm
also has some basic, very useful programs that use these Order
values.
1 2 3 4 5 6 | -- max : comparable -> comparable -> comparable max 1 0.9 -- min : comparable -> comparable -> comparable min "abc" "xyz" |
About how the two strings "abc"
and "xyz"
are compare
with logic, we will save it for the next article.
(unpublished) [Declarative Programming + Elm] Lesson 5 – String & List