[erlang-questions] Type def and spec syntax
Fred Hebert
mononcqc@REDACTED
Mon Oct 3 13:16:29 CEST 2016
On 10/03, Robert Virding wrote:
>And it if can be used in a
>meaningful way why isn't it documented? I think that having syntax which
>can never legal is a great way to complicate things. Which we don't need.
The three samples for syntax were:
-type atom(X) :: list(X).
-spec foo(Y) -> integer() when atom(Y).
-spec foo(Y) -> integer() when atom(Y :: integer()).
So here's a valid way to use them that is useful, at the very least in
some cases:
-module(mod).
-export([main/0]).
-type collection(K, V) :: #{K => V}
| dict:dict(K, V)
| gb_trees:tree(K, V).
-spec lookup(K,F,C) -> V when
C :: collection(K, V),
F :: fun((K, C) -> V).
lookup(K, F, C) -> F(K, C).
main() ->
C = maps:from_list([{a,1},{b,2},{c,3}]),
lookup(b, fun maps:get/2, C),
lookup("bad ignored type", fun maps:get/2, C),
lookup(b, C, fun maps:get/2).
This module defines an accessor function using the parametrized types
and 'when' parts of typespecs syntax. Sadly the analysis is currently
not good enough to figure out that "bad ignored type" is not an
acceptable value of `K' for the lookup (it appears dialyzer does not do
the parametrized inference this deep), but in the third call, it can
definitely infer that I swapped the collection and the accessor
function:
mod.erl:13: Function main/0 has no local return
mod.erl:17: The call mod:lookup('b',C::#{'a'=>1, 'b'=>2,
'c'=>3},fun((_,_) -> any())) does not have a term of type
dict:dict(_,_) | gb_trees:tree(_,_) | map() (with opaque subterms)
as 3rd argument
Had I otherwise defined my spec as:
-spec lookup(K,F,C) -> V when
K :: atom(),
C :: collection(K, V),
F :: fun((K, C) -> V).
Which adds a constraint that keys must be atoms, Then dialyzer would
have caught my error:
mod.erl:17: The call mod:lookup("bad ignored type",fun((_,_) ->
any()),C::#{'a'=>1, 'b'=>2, 'c'=>3}) breaks the contract (K,F,C) ->
V when K :: atom(), C :: collection(K,V), F ::
fun((K,collection(K,V)) -> V)
If you're using rebar3, you should also be getting colored rebar3
output, which does make the error a lot easier to see by putting the bad
value in red and the piece of contract it breaks in green*:
http://i.imgur.com/AjNgVCB.png
Regards,
Fred.
* we should find a way to somehow parametrize the colors to help
* colorblind users I guess.
More information about the erlang-questions
mailing list