Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Actually, I think the next big unlock in user adoption is static typing. Lack of it is frequently cited as the number one reason that makes people hesitate in switching to Elixir. I know it is an active research project right now, and I hope it bears fruit.


For me personally, this is not the case. I work in multiple languages, some static, some not. And I have as many bugs in the one as the other. I add strings to numbers less in static ones, but I tend to make more design mistakes, because I have to steer through the constraints of the type system.

I view "must have static types/compile time checking" types as a bit reductionist. It's like saying "all food must be seasoned with salt." Salt's a good seasoner. For some meals, it's a must have. For others, it's a nice to have. And for others, it actually detracts. Compile time checking fits in the larger context of what programming in a given language is all about. Syntax, libraries, ecosystem, tools, execution semantics, runtime components. All of these compose for an end result. And typing plays a different role for each composition.

I've been doing Elixir off-and-on for about 1.5 years now. The community is great. If I personally, had to lobby for "next big thing", it would be having a real IDE. I did Smalltalk for 20 years. I want an IDE where I work in modules/functions, not files and do/end syntax. I want a formatter that is not a PHD paper on generalized layout. I want refactoring tools. Inline macro expansion visibility. If I were independently wealthy, I would work on just such a thing in my spare time.

ElixirLS and VSCode are OK, but so so limited really.

What makes Elixir a standout candidate for a killer IDE experience is it's simplicity. Simple execution models make the language easier to model, navigate, and so IDEs don't need parse engines that are constantly needing updating (I'm looking at you Kotlin/Compose). Elixir as a language eats its own dogfood. It's sad to me that the Xerox Parc folks exploited this so beautifully with Smalltalk, but Elixir is stuck in the file editor mode still. :(


I felt the same way about static types, until I had the misfortune to work on an absolute disaster of a codebase (happened to be in Javascript).

The worst case for a dynamically-typed codebase is so very much worse in high-level languages.

Admittedly, the immutable data structures in Erlang/Elixir help offset this.


> And I have as many bugs in the one as the other.

The case for types is very strong in Javascript though.

I also use Ruby for backend and TypeScript for frontend and see no problem with that. Some languages are well suited for dynamic. Sometimes not just due to the language but the community + culture around it. Ruby codebases are also very heavily test driven which helps compensate and the inherent flexibility/developer experience of Ruby can't be matched. Elixir being the only close match.


Seeing as you've adopted TS, have you had the chance to look into Sorbet? The Ruby type-checker?


Isn’t that abit chicken and egg tho? Static typing is what really makes a language amenable to powerful IDE functionality…


That would make sense. More information, better IDE.

But it has not been my experience. Nor some of my peers. Despite a meh text editor, the Smalltalk IDEs (Smalltalk/V, VisualWorks, and VisualAge) were amazing. The original "refactoring" work done by John Brant and Don Roberts was pioneered at UIUC in these environments. Their adaptation to the different IDEs just improved them.

I remember sitting next to John and Don at OOPLSA and speculating that refactoring inside of Java (Eclipse was The New Editor at the time) should be superior in Eclipse vs Smalltalk because Java had more type information to work with. John and Don, both Smalltalk enthusiasts in those days, admitted they had anticipated that as well. And they did a bunch of work trying to port refactoring stuff to Eclipse. They were surprised to discover it wasn't so. But it's not typing vs not. It's simplicity vs not. When I asked if that meant that rising start Ruby would benefit from their refactoring work, they said that too was hard. Don explained that in a nut shell, it was the AST. Much of what tools/IDEs do is work with a model of the language. The Smalltalk AST had 15 polymorphic objects to represent its language model. Ruby was 90+ and climbing at the time. Java was insane. Their take was that while typing might add some information, the combinatorial explosion of modeling the language just made tooling for the language more difficult. It was an interesting insight.

Elixir/Erlang has a language model that is even simpler than Smalltalk in some ways. The trickiest part is the macros.


I hear you, but working primarily in php, the amount of lines of correspondence to type checking is wearing


I left elixir and went back to Go because statistic typing.

The elixir project I was in had several dozen developers on it and specs were not enough. I always had to backtrack through several calls and/or run the code and dump the data and then capture the example data as a comment so future devs could know what was coming into the function. Not a great solution.


Based on the number of attempts to add static typing to Erlang, I don't see this ever happening.

I know the author of Gleam is going full-time working on it, but I really know much about it or how it gets around the problems with statically typing message-passing. I'm perfectly happy working in dynamic languages and find Elixir's type hinting to be more than adequate.


You've been able to write PureScript compiled to Erlang for years. PureScript is a well tested language at this point, and the Erlang compilation works very well. Statically typed message passing is a non-issue in practice and it has been a bad reason for not having it the whole time.

I've been using Elixir since 2015 and can confidently say there is no use case I would choose Elixir for over PureScript for the BEAM. In practice my projects are Elixir + PureScript because we can have them interoperate, but there are zero technical reasons to choose Elixir over PureScript for BEAM work.

Edit:

`dialyzer` and similar tools are unusable for almost all sizes of projects in part because they're badly made, they're too lax and have zero useful abstraction properties. Making a spec generic, for example, is an exercise in futility, whereas an actual type system has no issues with expressing that very basic property.

Edit 2:

As an upside you also have PureScript for your frontend, so you can just write everything in the same language regardless of how much frontend work you expect to be doing. PureScript has great bindings and a great story around React (it actually fits better since it's a purely functional language, so things like "You can only do effects in `useEffect` actually are enforced and make sense) and also has its own frontend framework in Halogen which is very nice.


I'd like to see someone tackle a PhD thesis (or ten) on applying formalism to the concept of migrations. I suspect there's a missing aspect of type/group/category theory that's at least as big and important as variance is.

I think it might already mostly exist, it just isn't organized into a discipline.


While it's not as robust as static-typing, compile-time type checking for Erlang has come a long way. Eqwalizer works pretty well, though but I may be biased since my employer sponsors the project.

1. https://github.com/WhatsApp/eqwalizer


I really don’t get this, personally. I’ve worked in Java, Ruby, Typescript, Elixir, JS, and a bit of Elm and I literally never feel like I’m missing anything by not having static types in Elixir. This is doubly true with web based projects.

What are people looking for that they might get from static types?


I used to think this, but nowadays I avoid any language that doesn't have static typing.

The difference in tooling support/IDE completions I get on practically any language that has types vs those that don't is just too drastic for me.

It's also so much less mental load to have to always remember the types in my head.

Another issue I've seen in dynamic languages is when people do try to document the types via comments or otherwise, but then this drifts from reality due to not being updated.

I actually tried elixir and this is one of the main things that turned me off it.


Elixir does have a very good autocomplete despite the dynamic typing, it's probably the best autocomplete I've ever seen for a non typed language.

The reason for that is simple, the language works with modules and data pipes, not objects which means there's way less magic to parse


Completions in Elixir in VSCode are as good as anything if seen in intellij for Java, through that may be a low bar.

As for the burden of the mental model, I can’t really speak to that. In Elixir I usually try to think in data shapes or structures which can be matched on by function heads. I only think of types at the edges of the system.


ElixirLS developer here. Nice to hear that people like the autocompletion but comming from .net/java I think it still can do much better. It’s not very context aware and poorly handles code with parse errors


It always works well enough for my purposes.


It's way less of an issue due to vscode/elixir-ls auto running dialyzer in the background


In a large JavaScript codebase that's partway to being a TypeScript codebase, I find myself constantly having to insert `console.log` statements to find out what attributes some object actually has. Plus, our number one source of crashes and errors is unhandled null/undefined because someone didn't realize a parameter might be nullish. Static typing would basically eliminate both of those issues.


I hear this about big JS codebases but the 7 year old Elixir app I work on is many 10s of thousands of lines of code and we just don’t have that problem.


It's not nothing but it's rare. After about two years I finally had a type error. It wasn't horrible, though, just caused extra log lines.


It’s not that we never have type errors, it’s just that they’re the least frequent kind of error I see monitoring sentry. We try to do a zero exception policy, so we’re really on top of what kind of errors are happening.


For me:

- Ease of refactoring once the project got to a certain size.

- Preventing a lot of my stupid bugs (typos, passing the wrong type etc.).

- Quicker and easier understanding of argument and return types. The types are a form of documentation!

- Auto-completion and inline docs for library functions.

- Fewer tests needed, since everything the type system does has to otherwise be tested by a manually written test.

Just things anyone would tell you that appreciates static typing.


I’ve worked on some pretty large codebases and while there’s usually no IDE button for it, there are good and well known patterns for refactoring dynamic code.

As for bugs, the research on this has always been mixed at best, I guess YMMV.

I’d personally argue that the structural typing in Elixir is more useful and practical than the types in most popular static languages like Java or TS.

Mostly I think it’s a wash where you get a little but give up some useful things too.


Size of projects and lifetime of project. Team members swapping in and out, moving project/repo ownership to another team, ability to make simple changes to a code base without having full understanding, etc.


I'm working on a 7 year old application now with 60+ past contributors, 3-4 teams working in the code base, 3,500 elixir files, and some semi-complex dependencies and I can honestly say that most of it is pretty easy to work on. We have one section that is full of some really thorny code, but that's because it relies heavily on code generation and that's rough in most languages. Onboarding usually only takes about a week, less sometimes.


Every time people talk about static types and the lack of them in Elixir I chime in to repeat that it is a misconception to think of typing as a black and white issue.

Typing systems exist on a spectrum: I constantly get type issues on Javascript and Python, refactoring is a nightmare without a ton of tests, while it was never a big issue in Elixir. Yes, its typing system is inadequate, and dialyzer isn't great, but in practice it is not that much of a problem. Pattern matching saves the day, and type errors found in rarely used code paths, what's the worst they can do? Crash the process? That's the least of our problems on the BEAM.

I've maintained a big data ingestion system that kept getting fed with bad, unforeseen data and it's never gone offline in the 3 years I've overseen its operation. If a bug causes your program to segfault or throw a NullPointerException, you will definitely want to have a strong typing system.


A type system saves a lot of time when reading code that has been written by other people and has evolved over time. In Elixir, I often end up adding debugging statements to code and running it, just to check the data structures.

A type system also gives additional assurances when changing code that is used from many places. It's so nice to make a change and have additional confidence in it because the type system is happy with it.

I can't think of many bugs that I've seen that would have been prevented by a type system. I'd still like to have a type system though, it's sort of extra documentation within the code.


I agree 100% and I'd add, static typing helps when you inherit a poorly written codebase. This unfortunately is probably 99% of codebases in the wild. It has happened so many times when i've seen a lack of test coverage, a lack of understanding of the codebase but the business requirement to make changes.

Having a type system in place makes minor refactoring possible in this nightmare scenario.

I have been in the situation of poorly written ruby codebases and I can tell you 100% that I would prefer to have a poorly written java codebase with its static types. I prefer ruby as a language but man when it's bad, it's terrible. Just trying to work out the intent of a function when multiple types are passed in as the same argument over the codebase is pure hell.


I’m currently doing two startups: one with rapid consulting-esque development and one more long term B2B one. I would 100% be using Phoenix for the the majority of the projects in the former if it had static typing. Have been a fan since release but, for me, it’s a hard requirement for anything that isn’t a personal project


Has anyone figured out how to do static typing in Erlang yet?

FB a few years ago announced they were going to work on it for WhatsApp but then it was indefinitely delayed. There’s also been a few other attempt, but I don’t believe anyone has succeeded.

I know Gleam exists but haven’t dug into it.

Anyone more in the know care to share?


Jose has been working with some PhDs to attempt to implement static typing

https://elixir-lang.org/blog/2022/10/05/my-future-with-elixi...

In the meantime I don’t know what people have against using @spec. It’s a far more powerful type specification than the majority of static-typed languages out there


Dialyzer is almost always right but I've been using Elixir for around 4 years and I occasionally still find it difficult to decipher its verbose and deceiving messages.

I previously worked with TypeScript which felt like a major productivity boost but I've ran into a few instances where Dialyzer came up with the most cryptic error message that took me at least an hour to figure out. It really sucks when that happens and I wish there were more high quality learning materials that would dive into Dialyzer.


Yep, I've had some weird errors with Dialyzer, but in the mobile world I've had some similarly baffling errors from Kotlin and Swift, particularly around lambdas and generics. Let's not forget that the typing flexibility allowed in Elixir is really quite powerful compared to other languages. (e.g., function signatures can have guards, union types, and pattern matching)

I wish some LLM magic sauce could be applied to compiler and linter warnings in general that provide a context-appropriate plain language explanation, along with suggestions and automated fixes.


Typespec is a nightmare to work with. The error messages are arbitrary and at times misleading. I use it because it is better than nothing, but it has much room for improvement.


I think I've encountered a couple of times where I've gotten obscure errors, and I agree that error messaging needs to be improved. On the other hand, every time it's pointed out an error, it was right. And IMHO union type-checking alone puts it above most popular static-typed languages out there.

The other problem with specs is that they can become out of sync with function signatures.


> In the meantime I don’t know what people have against using @spec.

It's not ergonomic enough (you end up writing function definitions twice).

And there's very little tooling to help automate the process: if you return the result of a function call, good luck figuring out the spec for that if that function is in a library somewhere


> Actually, I think the next big unlock in user adoption is static typing.

From reading that post, it sounds like Jose does not believe static typing is needed. But a nice to have to address a very narrow set of use cases that primarily would help for documentation, not bug mitigation.


I think that Jose makes a solid case that static typing doesn’t bring as much to the table to Elixir as most people believe, but enough people point to the lack of it as a reason not to adopt the language that it’s worth addressing. Again, I think @spec is great and people should use it more – just treat the dialyzer warnings as errors.

Edit: Not sure why the downvotes, but the talking points by Jose are on his ElixirConf keynote

https://www.youtube.com/watch?v=Jf5Hsa1KOc8&t=408s

I'm not saying that types aren't a useful addition to Elixir, just that many people have wrong claims as to how they could be a useful addition to Elixir.


You've been able to write PureScript that compiles to Erlang and has perfect interop for years, via `purerl`[0]. Using it with Elixir is as simple as adding `purerlex` as a compiler and having your PureScript code automatically compile when `mix` compiles things, and off you go.

In terms of the typing itself, it's exactly what you get in all of PureScript, strict static typing with no `any` or the like. Using `Pinto`, the de facto OTP layer in PureScript your processes are typed, i.e. their `info` messages & state are typed, which means that they are all much more like strongly typed state machines than anything else.

You can see an example of a basic `gen_server` here:

https://pastebin.com/UTEfz7Wg

The differences aren't very big in terms of what you'd expect to be doing. One small thing to note is that the `GenServer.call` expects a closure to be passed instead of having the split between `gen_server:call` & `handle_call`, removing the need for synchronizing two places for your messages being sent and handled.

0 - https://github.com/purerl/purerl

Edit:

As an upside you also have PureScript for your frontend, so you can just write everything in the same language regardless of how much frontend work you expect to be doing. PureScript has great bindings and a great story around React (it actually fits better since it's a purely functional language, so things like "You can only do effects in `useEffect`" actually are enforced and make sense) and also has its own frontend framework in Halogen which is very nice.


The type checker from WhatsApp is open sourced and actively used. See https://github.com/WhatsApp/eqwalizer




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: