From PureScript's point of view, on the contrary, many concepts of JavaScript are still relatively vague.
A few days ago, I saw the discussion about the equality of js in the group, and I felt that the js design was quite unclear.
If you use ===
in js, you encounter
- Literals and null/undefined, judged according to value (I don't understand NaN...)
- Array, Object, judge by reference
But as the author of calcit-js, I want to say that these are not the nature of the equality of the data itself.
The semantics in the interpreter is entirely the interface exposed by the programming language author.
Judging references to judge whether they are equal, it will be very fast when running instructions, but this is not the semantics we want in our business.
When we encounter data in the business, we need to judge whether it is "equivalent" or not, we need to judge according to the value,
When we use a combined data structure to represent data, we need to recursively judge based on the structure.===
js is just a function that encapsulates and exposes the underlying capabilities of the platform, not for functional programming.
Let's see how to determine whether they are equal in PureScript.
Before starting, you need to define a data type, for example, I call it Cirru
directly,
data Cirru = CirruString String | CirruList (Array String)
The meaning of this code is that I have set a type Cirru, there are two cases,
One is the first possibility constructed by the data constructor CirruString "a"
One is the second possibility constructed by the data constructor CirruList ["b"]
For example, when we use two simple data to make judgments,
(CirruString "A") == (CirruString "B")
PureScript type checking will report an error, thinking that it can't find a way to deal with this type of Cirru,
No type class instance was found for
Data.Eq.Eq Cirru
while applying a function eq
of type Eq t0 => t0 -> t0 -> Boolean
to argument CirruString "A"
while inferring the type of eq (CirruString "A")
in value declaration main
where t0 is an unknown type
Because it is a functional programming, it actually ==
back to a function eq
,
eq (CirruString "A") (CirruString "B")
It is judged by function, but eq
is only a general definition in type class.
eq :: a -> a -> Boolean
https://pursuit.purescript.org/packages/purescript-prelude/5.0.1/docs/Data.Eq#v:eq
Among them, a
is a certain type, but he does not know the 0610132e5d853f corresponding to eq
, so he got the above error.
No type class instance was found for
Data.Eq.Eq Cirru
while applying a function eq
of type Eq t0 => t0 -> t0 -> Boolean
to argument CirruString "A"
while inferring the type of eq (CirruString "A")
in value declaration main
where t0 is an unknown type
As a js programmer, of course, you will also have some common ways to deal with it, "Isn't it enough to judge directly recursively?"
Then PureScript also provides such a way, you can integrate a built-in implementation derive
derive instance cirruEq :: Eq Cirru
In this way, when you judge again, you can get the desired result.
main = do
log $ show $ (CirruString "A") == (CirruString "B")
log $ show $ eq (CirruString "A") (CirruString "B")
log $ show $ (CirruString "A") == (CirruString "A")
log $ show $ eq (CirruString "A") (CirruString "A")
log $ show $ (CirruList ["A"]) == (CirruList ["A"])
=>> spago run
[info] Build succeeded.
false
false
true
true
true
Or, another more common way is to define the implementation of eq
For example, such code, through recursion, turns the judgment into a judgment of internal data.
instance cirruEq :: Eq Cirru where
eq (CirruString x) (CirruString y) = x == y
eq (CirruList x) (CirruList y) = x == y
eq _ _ = false
Finally, eq _ _
indicates the remaining possibilities that are not covered.
From the principle of this code, you can completely define the rules for whether the data is equal or not.
Even if you define (CirruString "A") == (CirruList ["A"])
equal, you can write it out
instance cirruEq :: Eq Cirru where
eq (CirruString x) (CirruString y) = x == y
eq (CirruList x) (CirruList y) = x == y
-- 看这行
eq (CirruString x) (CirruList ys) = if (length ys) == 1 then (Just x) == (head ys) else false
eq _ _ = false
You can simply think that the type class first defines a set of interfaces, including eq
,
Then after other types are defined, the corresponding eq
also needs to be defined before they can be used for calculations.
JavaScript is used as a scripting language, and one of the special cases is hard-coded on the language interpreter.
To find an accurate understanding, you have to go back to the definition of PureScript.
It can be seen that at the semantic level, we will not touch the judgment of whether the addresses referenced by the memory are equal.
When you use FFI to call js in PureScript, you may encounter,
However, these hardware-related implementation details are encapsulated in the bottom layer of the language implementation as much as possible to hide.
This article is some of my study notes and Xinde, and the terminology used is not very accurate.
If you need a more precise concept, you may need to look through Haskell related documents,
Or go to some books recommended by Juju to find the answer.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。