Qqwy

Qqwy

TypeCheck Core Team

Macro idea: total case statements

Hi everyone!

I recently had an idea. This is by no means a revolutionary concep, and other people probably have thought about it before (but maybe not in the context of Elixir), but I think it might be a useful one.

I have not gotten around to (attempt to) implement it yet. I do think it is possible (and of ‘average’ implementation difficulty. Not trivial, but not ridiculously hard either), but I would like to give the community the opportunity to shoot holes in the idea, as well as gauge if I am the only one excited about this, or if other people would like to use it as well.

Total Case Statements

It is very frequent that we pattern-match in a case-statement or function-head on the different possibilities a value might take. Of course, since Elixir is a dynamically/unityped language, a value might be ‘anything’ at any given time, but usually we expect only one of a small subset of these values, especially when we are using a(n approximation of a) sum type. Examples of those are for instance:

  • true | false,
  • [] | [head | tail]
  • :lt | :gt | :eq
  • {:ok, value} | {:error, problem}-tuples,
  • Ecto.action() :: nil | :insert | :update | :delete | :replace | :ignore
  • The atom-names of the fields in your struct.
    etc.

Now, it would be nice if we can somehow indicate that there is a case-statement where we expect such a sum type, and we want to make sure that we have cases for all possible values of that type. In a statically-typed language, this is usually built-in. In a dynamic language, it is not. But if we indicate to the case-statement the typespec that we want to handle, then it could be able to check if we have implemented clauses for each of the inhabitants of the type.

So I propose a macro, with a signature like e.g. total_case typespec, value do ... end, which could be implemented in a library, which would:

  1. Check, at compile-time, if the different match-handlers in the block together cover all possibilities of the type that is passed in.
  2. Maybe (if possible and not ridiculously hard to implement) warn about clauses that prevent later clauses from ever matching.
  3. After this check, compile down to a simple case value do ... end.

Sounds this useful to anyone?
The main thing that I don’t know about currently (besides having not enough spare time to start working on this right away) is how easy it is to programmatically interpret typespecs at compile-time.
It might also be possible that Dialyzer/Dialyxir already does some case-checking; this is something I don’t know, since until today I have struggled to set up + configure Dialyzer properly for my code. But even then I think that having a macro that would enforce this behaviour once set up would make a lot of sense over/alongside using an opt-in typechecker.

What do you think?

Most Liked

lpil

lpil

Creator of Gleam

I think this would be fantastically useful and I previously started work on such a macro before getting distracted by Gleam.

You can see the API I was working with here → sum/lib/sum.ex at master · lpil/sum · GitHub

If you build it I certainly would use this :slight_smile:

OvermindDL1

OvermindDL1

Yep, but it’s also not ‘total’, meaning that if something new is added elsewhere it may (often won’t) catch it and tell you to add a case for it.

LostKobrakai

LostKobrakai

Isn‘t a function with many heads essentially a case statement, which you can typespec?

Where Next?

Popular in Discussions Top

Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New
lorenzo
Hey everone! I created a prototype for my app using Nodejs for the api. But the framework I chose wasnt great (in general theresnt any g...
New
nunobernardes99
Hi there Elixir friends :vulcan_salute: In a recent task I was on, I needed to check in two dates which of them is the maximum and which...
New
Ankhers
Just a little information upfront. Generally speaking, if I feel like I need to either break a pipe chain or use an anonymous function in...
New
PragTob
Hey everyone, this has been brewing in my head some time and it came up again while reading Adopting Elixir. GenServers, supervisors et...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
rower687
Hi all, I’ve been reading a lot about the “let it crash” term and how supervising processes and the whole messaging passing make an elixi...
New
und0ck3d
Hello everyone! A few days ago I’ve created a topic here about how people were creating CMSs with Elixir and Phoenix. I’ve been studying...
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New
slashdotdash
Phoenix Live View is now publicly available on GitHub. Here’s Chris McCord’s tweet announcing making it public.
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52341 488
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47930 226
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New

We're in Beta

About us Mission Statement