Statically typed languages on BEAM

what are the most popular and to your opinion interesting statically typed language for BEAM?

1 Like

The only statically typed language on the BEAM that I am aware of is alpaca.

3 Likes

I see two interesting new entrants in the space:

Both projects appear to be in early stages.

6 Likes

I hope one day elixir can (optionally) be one :079:

5 Likes

why optionally is in parenthesis?

1 Like

Backward compatibility stuff

1 Like

typed elixir looks like a great proof of concept in this direction.

1 Like

Kind of dislike the approach there, I prefer something that define typed var under one statement.

We can assume all untyped var as ‘auto’ for backward compat.

The downside maybe the typed var definition need to be enclosed with special chars eg. ::int::var_name so parser can differentiate it.

1 Like

Entirely me screwing around… ^.^;

I was trying to make it to fit the current syntax and use the existing functionality rather than add new syntax. I was trying to make it be as simple to use as just replacing defmodule with defmodule_typed or whatever (then fleshing out some specs if you were missing those and fixing errors that it finds). I’d love to work on it more someday, but rather busy at work currently.

For something that still used the Elixir AST but built new syntax see my MLElixir thread.

3 Likes

Llixer seems more interesting than MLElixir, honestly :smile:

1 Like

Heh, more powerful overall for sure, though lfe is more fleshed out by far (though not elixir’y), but it does lack read-macro’s… ^.^;

1 Like

I agree. Coming from a Java background I really miss static typing. Having typespecs is great for documenting functions but they only work with Dialyzer, as opposed to having a built-in static type checker. I don’t favor that approach but it’s fine even though the success typing that Dialyzer does doesn’t catch as much as other static type checkers might.

However, the place where I really miss static types like Java is for documentation. It’s so easy when writing String str = Foo.bar() to figure out that Foo.bar() returns a string. However, in Elixir, str = Foo.bar() isn’t so easy to figure out, especially if I write something like result = Foo.bar(). Then, I have to go digging in the docs to figure out what the function returns, and without great IDE support for things like mouse-over Javadocs in IntelliJ (unless this exists?), it’s not so easy. I love Elixir, but I certainly miss the self-documenting aspect of statically typed code like Java, and the ability to get instant feedback in IntelliJ if I try to do something like int i = Foo.bar().

2 Likes

ElixirLS (Elixir Language Server) supports automatically dialyzing your whole project and deps without any work on your part. This is done when saving your file, so you can spot these things pretty easily. I agree that success typing doesn’t catch everything and I much prefer strongly, statically typed languages (though much better ones like Haskell, OCaml, etc.), but there’s something to be said for how much you can actually do with dialyzer when it’s used consistently and without hassle, such as with ElixirLS.

Using DynamicSupervisor yesterday the automatic checker actually picked up an a spec error that was in the 1.6.0 release candidate and sure enough there was a fix for it on master. The automatic checking really surprised me in how much it helped/informed me while just working. Eventually we might even approach ghc-mod level usefulness where it helps your refactor your code into more idiomatic and effective patterns.

6 Likes

On the other hand, when you see foo.bar() in Java, you really have no idea what code will be actually executed (through interfaces, subclasses and what not). With elixir this kind of dynamic dispatch is very rare - most of the time you know exactly what code will be executed at each call site.

5 Likes

Yeah this right here is one of the 2 big things I really exceptionally hate about OOP design (the other being inheritance explosion)! Java, technically, is not really fully statically typed, because the second you add Object as an argument/variable/etc then it basically becomes dynamic type-testing… o.o…

/me coughs about closure…

1 Like

Absolutely I agree with this. It’s far better in Elixir than Java where you have to dig through a deep class hierarchy, and now that interfaces and abstract classes can have default method implementations, you have to dig through those too.

3 Likes

Well, I don’t fancy static type.

For readability reason, I feel that pattern matching is clear enough for me, even clearer than Java’s explicit type declaration because pattern matching not only shows the types but also shows what the expected values look like. In fact, I hate Java’s static types. It just puts too much burden on the programmers.

For performance reason, I don’t think adding an afterthought type system on BEAM will bring any performance gain. Correct me if I’m wrong.

1 Like

Can you elaborate on how pattern matching shows the types? I’m not exactly sure how {:ok, result} = Foo.bar() really says anything about the result of that function call. Yes, it shows that the return value is probably an :ok or :error tuple but the actual return of the function that the programmer mostly cares about would be result which pattern matching doesn’t really help with. Maybe you could help me figure out what you mean.

{:ok, %HTTPoison.Response{body: body, status_code: 200}} = HTTPoison.get(url)

says quite a bit more when read about what’s expected. Even pattern matching on regular maps can signal quite a bit about what you’re expecting, with the added benefit that it also serves as assertions.

I don’t happen to agree that this is somehow a substitute for a type system (but I also don’t think Java has a particularly great type system anyway), but it does signal way more things than Java can in so little space.

4 Likes

Uh, but pattern matching and static typing are two different unrelated things, I don’t get the correspondence…

Like here is how you can pattern match in OCaml:

let matching_a_record_argument {a = a; b = b} = ...

let matching_a_record_argument_short_form {a; b} = ...

let matching_a_tuple (a, b, c) = ...

let matching a specific_integer 42 = ...

let matching_a_specific_variant_head (Blah a) = ...

(* Etc... *)

And it is all statically strongly typed. Just because Java’s type system is garbage doesn’t mean static typing is bad. Thus I ask, where is the burden?

Although the beam itself does not optimize for the types (though that could be added to the VM), you can still generate better code to give to the VM itself, which does indeed gain performance. Like see Elixir Protocols, those are linear match tests, so the more there is the slower each call gets, where if you knew the type then it could dispatch to the correct implementation directly without needing to incur that cost (as just one example of many). :slight_smile:

7 Likes