Reputation: 38478
I was reading about polymorphic types and the only example is for a tuple:
type queue(Type) :: {fifo, list(Type), list(Type)}.
I have a record like this:
-record(heap_node, { item :: any(), children :: [#heap_node{}] }).
-type heap_node() :: #heap_node{}.
Right now I can't pass a type parameter to the record. Is it possible in Erlang?
Upvotes: 2
Views: 242
Reputation: 13154
-type queue(Type) :: {fifo, list(Type), list(Type)}.
You would want to maybe represent this as:
-type queue(term()) :: {fifo, [term()], [term()]}.
That does not mean that these are consistent terms. term()
is an alias for any()
and just means that "you have a list of things", not a "list of homogenous things".
The more important question here is to ask what you are trying to do? What is the overall effect you are trying to achieve? The Erlang standard library has a large number of data structures that handle things like queue, bags, collection, sets, maps, trees, etc. quite effectively and efficiently.
The cases where you have a specific need, of course, is where you write you own. Every time you have a specific need you will find yourself either needing wide-open types (like term()
) or strict types (like non_neg_integer()
or #{integer() := pid()}
).
If we know a little more about the overall effect you're trying to achieve then it may be possible avoid expending a lot of effort reinventing OTP or the stdlib.
About Erlang's philosophy
Keep in mind that Erlang is not an academic language. It is a practical industrial language that suffers academic concepts as far as they are a natural outcome of effective language and system design -- in the era it was created.
It is:
(Incidentally, most other hot buzzwords you might think of also happen to describe Erlang, but this is once again only incidental. Erlang just happens to be fully buzzword compliant, and likely will be for a few more decades.)
That means Dialyzer is a permissible typer, not a strict typer -- it assumes type correctness until it can prove otherwise. Strict typers go the other direction, assuming type faults unless it can prove or infer otherwise. So no polymorphic types, as everything in the program is assumed to be polymorphic until type constraints can either be inferred through analysis or made explicit via the type language. You won't find as much power in the Erlang type system as in Haskell, for example -- but you will find that the system overall is geared specifically to get real-world programs out the door, though your mindset in development may be a little different.
See also: dialyzer not detecting guard violation when function is exported
Upvotes: 3
Reputation: 41578
You can create a type that is polymorphic in item
:
-type heap_node(A) :: #heap_node{item :: A}.
But A
wouldn't carry over to the children
field - those heap_node
records would still have an unrestricted item
field.
I tried using the type recursively:
-type heap_node(A) :: #heap_node{item :: A, children :: [heap_node(A)]}.
But Dialyzer didn't like that:
dialyzer: Analysis failed with error:
foo.erl:9: Illegal declaration of #heap_node{children}
Upvotes: 4