Elixir: Parametrized remote types for protocols

Created on 9 Apr 2018  路  11Comments  路  Source: elixir-lang/elixir

Being able to parametrize types ([pos_integer()]) is a critical feature of dialyzer. Support for parametrization is extended to some of remote types (:queue.queue(pos_integer())) but unfortunately not to all of them.

One I miss it the most ability to parametrize Enum (Enum.t(pos_integer())).

Elixir Feature Advanced Discussion

Most helpful comment

@fertapric that's a step in the right direction. The only issue is that @type/@spec/@opaque/@typep are specialish and I wouldn't want to introduce another special module attribute. But we could do it with something like:

defprotocol MyProtocol do
  @type t()
  @type t(my_type)
  @protocol_types t: 0, t: 1

  @spec my_fun(t) :: boolean
  def my_fun(term)
end

Or something of sorts.

All 11 comments

Parameterized types for protocols can be useful for documentation but I don't believe they will help dialyzer analysis.

@ericmj they should help once protocols are consolidated, which are most of the cases now.

It won't help with protocols themselves, but it should with things that use them. For example, we could make spec for Enum.map to be @spec map(t(a), (a -> b)) :: t(b). It is my understanding, it would improve analysis in places where Enum.map is used (but not for Enum.map itself - that's perfectly fine).

@josevalim Do we consolidate the typespecs as well? Otherwise I don't think Dialyzer can make the connection since the type has to be based on term: @type t(inner) :: term.

@ericmj that will be part of the work that needs to be done. :) Yes.

Can you elaborate on how would that work?

We know the shape of the types we dispatch on, so we can leverage that and
consolidate it in the same way we consolidate dispatch. However, for things

like parameterized types, the implementation will have to outline that.

Jos茅 Valimwww.plataformatec.com.br
http://www.plataformatec.com.br/Founder and Director of R&D

How do we know the shape of the types we dispatch on, do you mean we should assume that ImplModule.t is the type? What if the implementation type has a different number of parameters?

We will need a way to declare that the protocol type is parameterized.

That鈥檚 the part that needs to be done, I think.

Jos茅 Valimwww.plataformatec.com.br
http://www.plataformatec.com.br/Founder and Director of R&D

Here is an idea.

Protocol might use a module attribute @typeprotocol (or @type_protocol) or a macro to define the signature of the types; and the implementation might optionally define the types specified in the protocol using the regular @type syntax. During the consolidation process, the types defined in the protocol would be generated by inspecting the typespecs of the different implementations.

Here is an example:

defprotocol MyProtocol do
  @typeprotocol t()
  @typeprotocol t(my_type)

  @spec my_fun(t) :: boolean
  def my_fun(term)
end

defimpl MyProtocol, for: Foo do
  @type t(a) :: list(a)

  def my_fun(term) do
    true
  end
end

Thoughts?

@fertapric that's a step in the right direction. The only issue is that @type/@spec/@opaque/@typep are specialish and I wouldn't want to introduce another special module attribute. But we could do it with something like:

defprotocol MyProtocol do
  @type t()
  @type t(my_type)
  @protocol_types t: 0, t: 1

  @spec my_fun(t) :: boolean
  def my_fun(term)
end

Or something of sorts.

Was this page helpful?
0 / 5 - 0 ratings