phcurado

phcurado

@type representation for string maps

I was checking the documentation for elixir and erlang types for ways to represent a map in the typespec.

I have seen different projects defining types for maps this way:

@type user :: %{
  required(:first_name) => binary(),
  optional(:last_name) => binary()
}

And this would be a valid “user” map that follows the typespec:

%{first_name: "John", last_name: "Doe"}

I could not find in the docs whats the proper way to represent a map with string keys. I tried to create a similar type from above using string keys instead of atom keys:

@type user :: %{
  required("first_name") => binary(),
  optional("last_name") => binary()
}

but this doesn’t compile, which is kinda expected considering the documentation is clear that it should follow the given format:

      | %{}                                   # empty map
      | %{key: value_type}                    # map with required key :key of value_type
      | %{key_type => value_type}             # map with required pairs of key_type and value_type
      | %{required(key_type) => value_type}   # map with required pairs of key_type and value_type
      | %{optional(key_type) => value_type}   # map with optional pairs of key_type and value_type

But feels like the language could offer some support for this type:

%{"key" => value_type}                    # map with required key "key" of value_type

So maps with string keys have better representation when defining the @type instead of fallback to map() or %{binary() => term()}.

Most Liked

LostKobrakai

LostKobrakai

You noticed correctly that while there’s a :atom literal type, there’s no counterpart for strings. binary() is the most concrete type supported. While I agree that supporting that would be a real boon to documentation using types the syntax for manual type definition is just the smallest part to your ask. The larger part is extending the typesystem and users of the typesystem (dialyzer) to handle that new more granular type.

I can’t say for sure, but I can imagine that this might even be quite a lot of effort. :atom on the beam become a lookup on the atom table, so they turn essentially to an integer. Whole binaries might be a lot harder for the typesystem to keep track of, especially larger ones.

However given dialyzer already “drops granularity” eventually when it starts to track complex data I’d be curious if that couldn’t be used as an argument for allowing the definition of individual binaries. Dialyzer could maybe treat too complex binaries as binary(). The latest otp release actually included changes to dialyzer for nominal types: Eep 0069 - Erlang/OTP

Where Next?

Popular in Discussions Top

krainboltgreene
Today I noticed that when defining a embeds_many the new struct has a default of [] which is confusing since: You can have jsonb[] colu...
New
AstonJ
A recent chat with @leifericf inspired this thread - he’s worked in the gaming industry, and so it got me wondering what kind of industri...
New
josefrichter
Has anyone tried Github Speckit or similar projects like AgentOS, BMAD, etc.? They basically offer a bit more structure in context windo...
New
billylanchantin
If you’re not familiar with this fun bit of math lore, Paul Erdős, the famously eccentric, peripatetic and prolific 20th-century mathem...
New
markmark206
Every time I build a web app, I worry about a bunch of basic things (persisting data, knowing when to compute which things, keeping thing...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
travisf
In upgrading from Ecto 2 to Ecto 3 I’m dealing with a failing test. If I use ExMachina build(:address) I’ll get an error trying to put_e...
New
bartblast
It’s time to implement JavaScript interop for Hologram! Eventually, there will be Hologram wrappers for most APIs, but sometimes we’ll n...
New
kusokuzeshiki
I tried to generate pages with claude code and fluxon ui. I ask to claude code to generate real world page samples, the results are thes...
New
AstonJ
There seems to be a lot of buzz around DeepSeek at the moment, with some saying it’s a ChatGPT killer. The most remarkable thing (if they...
New

Other popular topics Top

TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
273 38985 115
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
dokuzbir
Hello, I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these buyer = %{ id: ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
Jim
As a follow up to my earlier question: I have the code compiling and running but not getting a successful login from the rest server. ...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement