本机 JavaScript 类型如何用 Elm 编写?

How do the native JavaScript types get written in Elm?

原生 JavaScript 类型是如何用 Elm 编写的?定义 List 的文件非常短且易于阅读:

我很好奇 Elm 如何为 JavaScript 证明一个类型安全的接口。 JavaScript 是手写的,还是从其他语言编译而来的 Haskell?


榆树的List类型

Elm 的关键线好像是...

module List exposing
  ( isEmpty, length, reverse, member
  , head, tail, filter, take, drop
  , repeat, (::), append, concat
  )

import Basics exposing (..)
import Maybe
import Maybe exposing ( Maybe(Just,Nothing) )
import Native.List

(::) : a -> List a -> List a
(::) = Native.List.cons

infixr 5 ::

head : List a -> Maybe a
head list =
  case list of
    x :: xs ->
      Just x

    [] ->
      Nothing

tail : List a -> Maybe (List a)
tail list =
  case list of
    x :: xs ->
      Just xs

    [] ->
      Nothing

这告诉我们headtail可以在Elm中定义,但是(::)操作必须用JavaScript定义。以下是 JavaScript 中与构造函数有关的一些关键行:

var _elm_lang$core$Native_List = function() {

var Nil = { ctor: '[]' };

function Cons(hd, tl) { return { ctor: '::', _0: hd, _1: tl }; }

...

return {
    Nil: Nil,
    Cons: Cons,

    // etc
};

}();

我对 { ctor: '::', _0: hd, _1: tl }; 这行特别好奇,因为 ctor 这个词是 functor 这个词的后半部分 - - 这可能意味着函子写在 JavaScript.


这些考虑很重要,因为我正在考虑编写 Tree a and/or QuadTree a 类型,从 Elm 内部编写(例如使用 Records)或编写一个供个人使用的模块。

另一个示例可能是 CircularList,但我现在只想关注树木。

认为 ctor是"constructor"的缩写,而List只是作为链表实现的。每个节点要么是空列表({ ctor: '[]' }),要么由一个值(在_0)和列表的其余部分(在_1)与[=17=放在一起]构造函数。

例如,列表 [1, 2] 将是 Cons(1, Cons(2, Nil)),完全展开后将是

{ ctor: '::',
  _0: 1,
  _1: { ctor: '::',
        _0: 2,
        _1: { ctor: '[]' } } }

你可以在 toArray 函数中看到它正在使用 xs.ctor !== '[]' 检查它是否已经到达列表的末尾,或者它是否应该将头部推到数组并保持去。

function toArray(xs)
{
    var out = [];
    while (xs.ctor !== '[]')
    {
        out.push(xs._0);
        xs = xs._1;
    }
    return out;
}

我的直觉是 List 的实现是用 Javascript 编写的,主要是因为它的构造函数是 []::,但 Elm 不允许中缀运算符作为构造函数名称。

例如,我们在 Elm 中使用 List 的方式意味着定义实际上应该是这样的:

type List a = ([]) | (::) a (List a)

即使我们在这些构造函数上进行模式匹配,它也不会在 Elm 中编译,因此使用了使用 Javascript 定义实现的快捷方式。

如果您使用不同的名称编写自己的自定义列表实现,javascript 输出与 List 的 javascript 实现相同。

type MyList a = MyNil | MyCons a (MyList a)

...产量...

var _user$project$Temp1467112617033056$MyCons = F2(
  function (a, b) {
    return {ctor: 'MyCons', _0: a, _1: b};
  });
var _user$project$Temp1467112617033056$MyNil = {ctor: 'MyNil'};

因此,我看不出有任何理由说明您提议的 TreeQuadTree 类型会因在本机 javascript 模块中编写而受益。我建议用 Elm 编写它们。