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

bartblast
With the core component system and HTTP/WebSocket infrastructure solid, it’s time to tackle Pub/Sub support. What We Have vs What’s Miss...
New
fklement
This is a thread to gather some information about the efforts of using elixir in combination with cars or vehicular systems in general. ...
New
SyntaxSorcerer
This is the start of my Elixir learning journal/journey. I plan to share my journey in this thread and am open to all feedback, construct...
New
Sergiusz
Hello everyone, I don’t know if my post is appropriate. If it isn’t, you can delete it. After a year of designing and defining the requ...
New
stevensonmt
Has anyone else ever wanted to merge two maps, but have the resulting map only include keys common to both maps? I think of it as analogo...
New
matreyes
I haven’t seen this paper being discussed by the community, but I think this makes Elixir more relevant than ever. TLDR; The paper...
New
paulanthonywilson
I like Umbrella projects and pretty much always use them for personal Elixir stuff, especially Nerves things. But I don’t think this is ...
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
isaacsanders
When I try to run my applications and I haven’t updated the dependencies, the output tells me to run mix deps.get. Why doesn’t the binar...
New
ScriptyScott
Hey Folks, I just spent the last couple of days doing a deep dive into using Swoosh with Amazon’s simple email service, check out this t...
New

Other popular topics Top

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
Tee
can someone please explain to me how Enum.reduce works with maps
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
AstonJ
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
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 42633 214
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

We're in Beta

About us Mission Statement