What are your concerns about a future type system for Elixir?

My concern is diversion: that disproportionate resources will be diverted towards a new focal point. Discourse will become dominated by the type system, at the expense of other concerns. Soon enough, the very course of the language will be perceived as resting on the resolution of formerly subordinate issues.

Brexit is the closest analogy I can think of.

9 Likes

I’m unsure if static typing would solve issues that existing solutions don’t. I’m concerned that Elixir’s flexibility could be compromised.

2 Likes

My main concern is when it would be safe to add to libraries for older version support.

I would love to see a couple of versions of Elixir released that know how to ignore any planned new types syntax before the syntax is enabled so that it is easier to offer older version support while taking advantage of new features like typing.

1 Like
  • Explosion of complexity. I don’t feel comfortable working with a language that I don’t fully comprehend. Typescript crossed that line for me. Can the types be kept simple yet still useful? Is there going to be a push for ever-growing list of features for the type system? The most complex code occurs when two somewhat orthogonal features interact with each other (I have bad experiences from C++). How is the type system going to work with macros?
  • Style mismatch. Having to deal with both the dynamic and typed styles of coding in a single codebase. For example, are we going to have Result | Error vs {:ok, result} | {:error, error} issues?
  • Degraded code readability. I don’t want to have to learn another language on top of Elixir. Typespecs feel foreign to me (e.g. ::) and I always need to have the docs open to declare a behaviour. Mixing types with other code negatively impacts the readability.mistake.
5 Likes

First of all - thanks a bunch for involving the community so early on in this journey that hopefully leads to an awesome type system @josevalim! I really enjoyed reading your early discoveries on what the type system might look like. Here are my top three worries:

  1. An obtuse syntax which makes Elixir type definitions a lot more confusing to read and write. Coming to Elixir from other languages about a year ago one of the hardest things to grokk was actually how to write idiomatic function signatures. Elixir has pattern matching, guard clauses, and @specs, that all hint at what the function params are expected to be. Adding a fourth thing that’s at least semi-related could potentially make function sigs even more complex.

  2. Language server / IDE integration not being robust enough. Right now the Elixir LS semi-regularly errors out for me and needs to be restarted (when using VSCode). I’ve often been in situations where the LS has stopped working, and Dialyzer therefore gave up on highlighting issues (or even worse, highlighting issues that aren’t there any more). If a type system is to be helpful for developer feedback I think these integrations need to be solid as well.

  3. Hard to understand error messages from the type system. I dread reading whatever Dialyzer spits out, and often end up just trying to figure out what the issue is myself instead.

Looking forward to watching the ElixirConf US talk! :slight_smile:

6 Likes

I am also concerned about the $ syntax. Most elixir code verbally describes what it’s doing, and creating something that would, unlike the & syntax, be sprinkled throughout almost all files that isn’t self-describing feels wrong. I personally would prefer a new keyword or something in combination with the $ syntax that is self descriptive, but there are challenges with doing that too, right?

2 Likes

Education

From my experience as a learner and a teacher any boilerplate adds complexity to understanding. People wouldn’t be able to make simple programs fast (in iex) while they are learning and will give up.

Simplicity

I came to Elixir to learn about concurrency, faced easy to read syntax and this gave me ability to learn more about functional like programming and work with processes (actors, real OOP). And oh my processing Is not something simple to get used to even with such concise syntax. I am afraid that language will get complicated and will start to compete with mainstream languages like C++, Java. And I’ll just move to Erlang because I don’t understand the point of mainstream languages. I droped Python because it’s a divided language now: there are several ways of types, several ways of concurrency (standart library doesn’t work with concurrent frameworks). And I feel more like Defensive Programming aproach with types and it’s not an easy way for programming.

REPL

Are we getting rid from REPL?
For me type system is something more about compilation time errors. I’d like to let it crash during runtime.

2 Likes
  1. Typecasting: I want to somehow type data structures, and ensure that either I have something like this in my hands or fail hard and fast in my code. Like, interacting with external APIs where I cast/transform received data into something more usable first thing in my code - the ability to hard cast eliminates a lot of “if” branches later on in the code. My fear: we get types without the casting, like in typescript. I want: in an ideal world something like serde in rust, where I can encode/decode stuff right From/Into (json/xml/
). A huge percentage of company business code usually is concerned with casting data shapes back-and-forth, so for me personally this would be a killer feature.

  2. duplication: the new types should automatically generate dialyzer specs or vice versa somehow - additional markup ontop of functions would be bad.

  3. compilation times: this already is noticeably bad when there is a big phoenix monolith with lots of code and dependencies and then ontop of it dialyzer runs from scratch for a significant amount of time. I see why it is that way and understand the reasons, but at least it shouldn’t get much slower.

3 Likes

Yesterday evening I finally watched it as well as your 2023 talk. I agree with most of the things you said in defense of a typing system (in Elixir). Naturally, I also agree with all the cons.

As for how this typing system will look like the only thing I understood was it would be used for interfaces (functions, callbacks) and structures. Now, since I myself already use typespecs for all non-trivial functions, I could get used to it but would still prefer it be optional, just like the typespecs, especially if the ambitions is to type variables within the function body one day. (I would, however appreciate if all your code in LV and other libs/frameworks had typespecs :).

Re the fear of a community split:

In my view there’s no room for fear that an optional typing system would “split the community” for as long as this optionality is implemented the same way the typespec’s is i.e. relying on typing where one sees fit. There where it’s not used the compiler should simply assume (correctly) that the proofs and restrictions might not be desired or that the user finds it unnecessarily litter the code. If a typed function invokes a non-typed function, by default the user will get a warning that can otherwise be suppressed on a case by case, module by module or even the application as whole basis. And that’s it. The time and the market will then judge best where and where to use it or not to use it while no “legacy” code would be ever jeopardized.

My 2c

I worry that the type system may:

  1. result in idioms that actually harm code evolution (catch alls/pokemons exhastiveness checks will hide future issues)
  2. destroy “coding the happy path” and “let it crash” semantics because the type system creates a tension that promotes the use of nanny coding standards / catchalls which may be well intentioned but ultimately harmful.
  3. not deliver much value vs the significant effort typing “types” to “keep the compiler happy”
  4. reduce productivity in the wrong place vs testing
  5. reduce readability, although I think “doctypes” would be a nice way to document possible function return values.
  6. be at a layer too high. If it’s not in the core of the beam then we lose the potential for exploiting it for optimisation and also may have an impedance mismatch “all bets are off” when using Erlang libraries that don’t use the type system.
  7. distract the community for a very long time.
  8. end up with multiple rail gauges in libraries, and it is likely to be polarising to the point some will embrace it and some will despise it.
  9. lead to similar outcomes like the early days of C programming before function prototypes, and we would need to declare the function twice, one in K&R style and another using the hipster ANSI C style with prototypes which meant using macros to harmonise the code so it could still compile with non ANSI C compilers.
  10. create a false sense of security. Testing is good, value matching and let it crash is excellent. This already provides more value further than types.
13 Likes

I worry that the type system will make the macro system more complicated or less powerful. Also, I worry that if Elixir does not have some type system it can never be adopted more broadly.

3 Likes

My concern: I hope types do not lead to a break in language continuity. The leap from Python2 to Python3 was IMO disruptive.

I hope types are introduced over a very long time period, in a series of small incremental improvements, with time for the community to absorb each change.

1 Like

I have some concerns but nothing too major.

  1. Will this be able to work with existing typespecs as written? I have a concern about duplication of effort.
  2. I’m concerned about IPC interfaces like Phoenix PubSub and just basic process message passing. How will that work, or will it simply be a limitation on the concept?
  3. How will this work with function heads? With typespecs as written, I can’t write a @spec for each head - just one. I want to be able to write a type definition for each function head if I want, though I’m not sure if the flexibility I want is achievable.
1 Like

I disagree here. I would say the major use for pattern matching is to pull apart structures and access fields within them, the type testing is very much a bye product of this. And yes, you can write your code to explicitly access fields in a structure but I personally find that pulling them apart in one got with a pattern is easier and clearer.

13 Likes
  1. Function definition verbosity

    As mentioned by José in an earlier topic, Elixir function definitions are typically already quite busy due to pattern matching and guards. Adding an additional line above the function definition containing the parameter and return types adds to this verbosity if we consider both the $ and def lines as a single piece of information to absorb about how the function is set up. My suggestion here would be to look at reducing some of the activity in the function parameters themselves (for example, moving pattern matching to a seperate line inside the function itself where applicable).

  2. Syntax differences from mainstream languages may hurt adoption

    Using a variation of the proposed $ syntax is quite different from how parameter types are defined inline in mainstream web development languages such as TypeScript, Python, and PHP (the baseline that many developers will be coming from). By using the $ syntax on the line above the function definition, we increase the amount of “oddness” to the language for those considering Elixir from these more mainstream languages. People prefer the known over the unknown; there is only a certain amount of “oddness” that developers will tolerate.

  3. Community adoption and documentation

    The @spec syntax has not been widely adopted among the community. For those considering adding @spec above their function definitions, a challenge is finding good examples and documentation, for example how to use types with Ecto. Without the new type syntax being added to the HexDocs of major libraries, it will be unclear how to use the types, and the path of least resistance will be for developers to not bother adding them. As a result, the new type system would be unlikely to see widespread adoption.

6 Likes
  1. Compiler speed in larger applications (where types are more likely to be used and have the most utility).
1 Like

As a library author, I generally want to support all Elixir versions that are officially supported. At the same time, I’d like to switch from type specifications to the new type syntax rather sooner than later to give library users all the benefits that come with it. I’m concerned that I (and other library authors) will have to make a choice between abruptly dropping support for older Elixir versions or waiting 2 years until all officially supported Elixir versions support the new syntax.

14 Likes

I’m worried the new type system won’t fix the pain points I have with Elixir. In Ocaml I can change a type or a function and immediately the compiler will point out every instance that needs to be updated. In Elixir the compiler can only help when a function is no longer found due to the arity changing.

2 Likes

I worry (without having seen the actual approach in depth, so these are abstract concerns) that

  1. writing “typeless” code would become more complex,
  2. the type system will be verbose and/or awkward to use,
  3. type inference will be largely missing or significantly {less powerful, more verbose} than that of OCaml or Elm.

That said, I am super-excited about getting type safety in Elixir, thank you! ; )

1 Like

Concern 1: verbosity. The first thing that drew me to Elixir was the clean, compact syntax. I worry this would take a big hit.

Concern 2: not sound enough? If we are going to do types do it 100% imo. I worry a half’n half approach will be worst of both worlds. Dart started out with soft typing and moved to sound typing. Lessons to learn from I think.

Instead of soft types, I would rather Elixir be the best dynamic lang it can be and double down on enforcing better code conventions in the ecosystem to mitigate type bugs and error handling etc. As a newish Elixir mixer I’m still confused if I should raise exception or return error atom tuple. Also to get more performance out of Elixir I think we could focus on core libraries running Rust under hood. Copy what Python did with C-langs.

4 Likes