[erlang-questions] Record typing for dialyzer

Kostis Sagonas kostis@REDACTED
Wed Nov 25 08:44:06 CET 2009


Bernard Duggan wrote:
> Hi list,
>     We have a lot of auto-generated record types that we use to allow
> our (newer, awesomer) erlang/mnesia code to interact with our (older,
> less awesome, but we're stuck with it for now) C++/mysql code.  It
> recently occurred to me that it would be a simple matter to add type
> specifiers to the records to give dialyzer (which we love to death) some
> extra info to work with.  And for the most part it was.  So we now have
> nice auto-generated records of the form:
> 
> -record( person{
>     id :: integer(),
>     name :: string(),
>     is_awesome :: boolean()
> }).
> 
> which is great (and already helped us find several bugs - have I
> mentioned we love dialyzer?).  We struck a problem, however, when we
> used one of our records in a select statement thus:
> 
> Match = #person{name="Bernie", id='$1', _='_'},
> mnesia:select(person, [{Match, [], [{{'$1'}}]}]),
> 
> At this point, dialyzer quite correctly points out that '$1' isn't an
> integer and '_' isn't a boolean and so we've got no business assigning
> them to fields typed as such.
> 
> My solution, then was to add an extra type definition:
> 
> -type search_spec() :: '_' | '$1' | '$2' | '$3' | '$4' | '$5' | '$6' |
> '$7' | '$8' | '$9'.
> 
> and change all the record definitions to something like:
> 
> -record( person{
>     id :: integer() | search_spec(),
>     name :: string() | search_spec(),
>     is_awesome :: boolean() | search_spec()
> }).
> 
> Now this solves the problem, but it really looks ugly and seems like
> kind of a hack and I can't help but feel like there must be some more
> elegant solution.  But I don't know what it is :)  Any input (even if
> it's only "nope, there's no better way to do it") would be greatly
> appreciated.

I am not aware of any cleaner way of doing what you want to do, so what 
you've done is how I would personally also do it.  The only thing I 
would recommend is to try to add these declarations as sparsely as 
possible, meaning try to add them only to the record fields that are 
used in match specifications in your program, not everywhere.

The problem is that you (and dialyzer) are up against a really bad 
design decision in the language here, namely the use of "special" atoms 
to represent variables in match specifications.  I sincerely hope that 
this is fixed by Erlang providing an alternative way of writing match 
specifications that does not lie about types.

Thanks for your thumbs up for dialyzer!

Kostis


More information about the erlang-questions mailing list