1

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.


题叶
17.3k 声望2.6k 粉丝

Calcit 语言作者


引用和评论

0 条评论