chulkilee

chulkilee

Typespec for Enumerable

I wrapped an API using pagination with Stream.unfold so that it returns Enum.t (Enumerable.t).

Is it possible to specify @spec of values that will be yield from the Enumerable struct?

Marked As Solved

alfert

alfert

You can of course write a spec for your function, where you say what type of values are returned. But you cannot derive it from the type spec of the enumerable or the stream itself. This has two reasons: First, the type of an enumerable, Enum.t has no type parameter, which would constraint an enumerable to, say an enum of integers. Secondly, the missing strict static typing of Elixir allows for putting all kinds of values into an enumeration. That is the reason why in the API of Enumerable the type element is only an alias of any.

What you can do is to spec your function in way to say it returns a list of a specific element type, e.g. list(integer). The diaylzer can then check, whether this specification is fulfilled in your program.

Also Liked

alfert

alfert

It depends what you want to do with the type specification. If it should be a help for the reader or programmer, than you can define your enumeration type for your API, e.g. something like

@opaque my_enum(t) :: list(t) | Enum.t

This compiles, reveals no details about the internal of type (thus @opaque) and you communicate your intention. But the dialyzer cannot help at finding type errors. The following snippet is wrong, but dialyzer does not complain:

  @opaque my_enum(t) :: Enum.t | Enumerable.t | list(t)

  @spec take_ten(integer) :: my_enum(integer)
  def take_ten(max) do
    max
    |> Stream.unfold(fn 0 -> nil; n -> {n, n-1} end)
    |> Stream.take(10)
  end

  @spec ten_ints() :: list(atom)
  def ten_ints() do
    take_ten(20) |> Enum.to_list()
  end

I assume that it comes from type union. It could be a list of atoms, because the stream functions are allowed to return enumerable of any type. And you cannot use Enum.t(integer) because it is not defined in the Enum module. This could be an interesting bug report and PR for the Enum module, because you could define type t this way:

@type t :: t(any)
@type t(x) :: Enumerable.t(x)

You need to specify properly all enum functions to take parameterized types. But I am unsure how the type definition on the protocol level works, in particular since Enumerable.t is not defined explicitly but seems to generated by defprotocol.

Where Next?

Popular in Questions Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
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
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
johnnyicon
Hi all, I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I'm trying to use Postg...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
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
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 49522 488
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
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
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
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
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New

We're in Beta

About us Mission Statement