[eeps] Multi-Parameter Typechecking BIFs

Andras Georgy Bekes <>
Wed Feb 25 12:49:00 CET 2009

> Proposal 0)
> > foo(_,{Width,Height,Depth},_) when is_integer(Width),
> > is_integer(Height), is_integer(Depth) -> ...
> >
> > Proposal 1)
> >
> > foo(_,{Width,Height,Depth},_) when is_integer(Width, Height, Depth)
> >
> > Proposal 2)
> >
> > foo(_,{Width::integer, Height::integer, Depth::integer},_) -> ...
> Proposal 3)
> foo(_, {Width,Height,Depth}, _)
>    when ?i3_coords(Width, Height, Depth) -> ...
> Proposal 4)
> foo(_, #i3_point(Width,Height,Depth), _) -> ...

> In this case, by golly, we have FIVE proposals on the table, not two.
Please also consider a proposal #5 written by somebody, which is the 
ability to use #2 syntax with user defined types. Example:

-type(i3_point() :: {integer(),integer(),integer()}).

foo(_, {Width,Height,Depth}::i3_point, _)

I think either #4 or #5 is the best.
Could you help comparing them?

#5 user-defined types used as type guard:
+ you don't have to write any extra declaration. You have written the 
type declaration for dialyzer, now you use that for one more thing.
- As in the above example, if you want to match the parts of the whole, 
you have to write (know!) the structure, i.e. that i3_point is a 
3-tuple and the order of elements is some fixed order.

#4 abstract patterns:
- You write extra declaration. Abstract patterns are new to the language 
and complementary to the current type declarations. You must write both 
the abstract pattern and the type declaration.
However, abstract patterns might be automatically generated from type 
declarations or the other way round. This is a step in a bad direction. 
We should not have two different things for describing the same. Either 
we should have abstract patterns or type declarations. The other must 
go. "If you add something, you need to take something away"
+ You don't have to know how the abstract thing is represented. 
#i3_point(Width,Height,Depth) will match a 3D point no matter if the 
representation is a tuple, a record, a list, whatever.

We also have a #6 proposal:

> > take advantage of the newly
> > introduced -spec syntax and making it possible
> > to tell the compiler to generate runtime guards according to the
> > -spec

Richard's opinion is:
> It is conventional to use type declarations to enable
> a compiler to *omit* run-time checks.  (Lisp, ML, CAML, F#,
> Haskell, Clean, ...)  Using them to cause the compiler to
> *emit* run-time checks is certainly original.

If I specify the type of a function, I want it to be executed only if 
the type is correct. I don't care if the compiler *emits* extra type 
checks or it *omits* the type checks beacuse it is able to deduce that 
my type declaration is never violated.

> Not the least 
> of the problems is that code that worked as its author
> intended (but was incorrectly annotated) would suddenly break.
Yes, this is a real problem, but note that we're talking about code that 
dialyzer told you will break. If you didn't use dialyzer before, you 
certainly didn't write the spec declarations. If you did use dialyzer, 
you most probably did read what it tells you.


More information about the eeps mailing list