How do the native JavaScript types get written in Elm? The files defining List
are surprisingly short and easy to read:
I am curious of how Elm does it's job of proving a type-safe interface to JavaScript. Is the JavaScript written by hand, or is it compiled from another language like Haskell?
List
TypeThe key line of Elm seems to be ...
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
This tells us that head
and tail
can be defined within Elm, but (::)
operation must be defined with JavaScript. Here are some key lines in JavaScript to have to do with the constructor:
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
};
}();
I am especially curious about the line { ctor: '::', _0: hd, _1: tl };
since the word ctor is the second half of the word functor -- which may mean a functor was written in JavaScript.
These considerations are important because I am considering writing a Tree a
and/or QuadTree a
type and it might be good to write from inside Elm (e.g. using Records) or to write a module for personal use.
Another example could be CircularList
but I just want to focus on trees for now.
My hunch is that the implementation of List
is written in Javascript primarily because its constructors are []
and ::
, but Elm doesn't allow for infix operators as constructor names.
For example, the way we use List
in Elm means the definition really should be something like this:
type List a = ([]) | (::) a (List a)
That doesn't compile in Elm even though we pattern match on those constructors, so the shortcut of using Javascript to define the implementation is used.
If you write your own custom list implementation with different names, the javascript output is the same as the javascript implementation of List
.
type MyList a = MyNil | MyCons a (MyList a)
... yields ...
var _user$project$Temp1467112617033056$MyCons = F2(
function (a, b) {
return {ctor: 'MyCons', _0: a, _1: b};
});
var _user$project$Temp1467112617033056$MyNil = {ctor: 'MyNil'};
Therefore, I don't see any reason why your proposed Tree
or QuadTree
types would benefit from being written in a Native javascript module. I'd recommend writing them in Elm.