[erlang-questions] [Dialyser] Type parametrized behaviours
Thu Apr 26 00:57:19 CEST 2012
On 04/24/2012 04:42 PM, Francesco Mazzoli wrote:
> I have recently updated some code to use the new callback signatures for
> behaviours. Before that, we simply used a .hrl file that we included in
> each implementing module.
> While hacky, the old approach had an advantage: we could include in the
> .hrl specs some types that were to be defined in the including file, and
> then used in type signatures.
> It would be useful to be able to parametrize behaviours by type more
> nicely, since most behaviours specs are dominated by 1 or 2 types
> (classically some kind of state) and as of now no typechecking takes
> place on those types. That might be achieved with some pre-processor
> directive, e.g. -behaviour_type(whatever).
> What do you think?
The first thing I think is that you have not fully understood the need
for having both a -callback and a -spec. In the general case, the
behaviour module needs to have a way to define what the callback module
*can* have as implementation of callbacks, not what it *should* have as
its implementation. For example, it's perfectly ok for the behaviour
module to say that there needs to be a callback function f/1 which can
return 'foo' and 'bar' and for the callback module to implement a
function that just returns 'bar'. So, we do need both these attributes
since they serve different purposes. This also means that the "header
file approach" does not work / is not flexible enough in general.
Now, regarding parameterized behaviours, I think that you need to
explain more concretely what you have in mind. Perhaps it's something
interesting but the example you gave in another mail of yours:
> To give a small example of what I want to do, a behaviour might define
> -callback step(state()) -> state().
> where `state()' is not define locally in the behaviour, but in each
> implementing module.
> I hope I made myself more clear.
unfortunately does not make matters any clearer...
If I understand what you are sketching correctly, the problem I see is
that since there will be no definition for state() in the behaviour
module, that module will impose no constraints on what state() can be.
Thus, your example is semantically equivalent to:
-callback step(X) -> Y.
for some arbitrary types X and Y. (Just take state() to be their union.)
The point is that the callback module is allowed to provide the
following implementation of step/1
step(foo) -> 42.
and dialyzer (*) is obliged to keep silent in this case. As I wrote this
case is actually fine. The callback module is allowed to implement only
a portion of what the callback spec specifies. How is that different
than what currently takes place other than perhaps requiring that the
callback module contains a definition for state()? (Perhaps as liberal
as -type state() :: 'foo' | 42.)
Anyway, can you provide a *precise* proposal for how you want things to
look and what checks dialyzer should perform in your opinion?
(*) Please use the correct spelling for dialyzer.
More information about the erlang-questions