原生JavaScript类型是如何用Elm编写的?定义List
的文件非常短,而且易于阅读:
我很好奇Elm是如何证明JavaScript的类型安全接口的。JavaScript是手工编写的,还是从Haskell之类的另一种语言编译而来的?
Elm's List
型
榆树的关键似乎是..。
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
这告诉我们,head
和tail
可以在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是函子这个词的下半部分--这可能意味着函子是用JavaScript写的。
这些注意事项很重要,因为我正在考虑编写一个Tree a
和/或QuadTree a
类型,可能最好是从Elm内部编写(例如使用记录)或编写一个模块供个人使用。
另一个例子可能是CircularList
,但我现在只想关注树。
发布于 2016-06-28 03:30:18
我的直觉是,List
的实现是用Javascript编写的,主要是因为它的构造函数是[]
和::
,但是Elm不允许infix操作符作为构造函数名。
例如,我们在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'};
因此,我看不出有什么理由可以让您建议的Tree
或QuadTree
类型从编写一个原生javascript模块中获益。我建议你用榆树写。
发布于 2016-06-27 15:57:54
我认为ctor
是“构造函数”的缩写,List
只是作为一个链接列表来实现。每个节点要么是空列表({ ctor: '[]' }
),要么是一个值(在_0
),其余的列表(在_1
)与'::'
构造函数放在一起。
例如,列表[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;
}
https://stackoverflow.com/questions/38064062
复制相似问题