Confused about spec/dialyxir: "Invalid type specification for function"

This is where your mental model breaks down: there is only and there can only be one update/3 function. That function may be implemented in terms of multiple function clauses - but they all belong to the same function.

The Erlang style of specs make that much clearer:

-spec foo(pos_integer()) -> pos_integer()
         ; (integer()) -> integer().

So strictly speaking the return type of SystemRegistry.update/3 is the sum type Transaction.t() | {:ok, {new :: map, old :: map}} | {:error, term}.

A more type-aware module API would have

  • SystemRegistry.update_with_scope/3
  • SystemRegistry.update_with_transaction/3
  • And a convenience function SystemRegistry.update/3 that delegates appropriately.

but given that Erlang/Elixir is dynamically typed you will run into functions that have only been typed after the fact rather than being designed with types in mind.

3 Likes