[erlang-questions] Dialyzer question

Tobias Lindahl <>
Tue Nov 15 08:23:01 CET 2011


2011/11/14 Steve Strong <>:
> That makes some sense, and indeed if I just export test/0 then it does work
> nicely.  Alas, do_something is what I really want to be exporting and if I
> do so, then dialyzer stops warning me.  I completely understand that in
> isolation, dialyzer has to infer that do_something can return any() - I was
> hoping that it would adjust that inference when in the context of the
> caller, where the mapping function is constraining the return type.

No such specializations happens for exported functions. If the
inference was stronger, we could find a type for do_something that
connected the type of the fun to the return type of the function using
type variables, but this is beyond Dialyzer. On the other hand, if the
function is not exported Dialyzer will propagate the union of the call
types, which in your case is just the single fun. That is why it finds
the specialized type in your case.

> Again, this seems analogous to lists:map/2, which is exported and yet
> dialyzer seems to do "the right thing".

There is hard-coded information in Dialyzer about lists:map/2 and
other commonly used library functions.

Tobias

> Confused :)
> --
> Steve Strong
> @srstrong
> Sent with Sparrow
>
> On Monday, 14 November 2011 at 11:58, Joe Armstrong wrote:
>
> Change export_all to
>
> -export([test/0]).
>
> Then you'll get this:
>
> test.erl:8: Function test/0 has no local return
> test.erl:9: The pattern {'rec2', _} can never match the type #rec1{}
>
> With export_all the arguments to do_something are totally unconstrained and
> can come from
> any wild place - so the inferred types are too permissive.
>
> With export_all typer infers the following:
>
>> typer test.erl
> %% File: "test.erl"
> %% ----------------
> -spec test() -> #rec2{}.
> -spec do_something(_,fun((_) -> any())) -> any().
> -spec map(_) -> #rec1{}.
>
> The (.... any()) -> any() is because the second argument of do_something can
> come from anywhere
> so there are no type errors
>
> But with -export([test/0]). we get this:
>
> -spec test() -> none().
> -spec do_something(1,fun((_) -> #rec1{})) -> #rec1{}.
> -spec map(_) -> #rec1{}.
>
>
> /Joe
>
>
>
>
> On Mon, Nov 14, 2011 at 11:40 AM, Steve Strong <> wrote:
>
> Hi All,
> I have a question on the behaviour of Dialyzer with higher-order functions.
>  Consider the following trivial code:
> -module(test).
> -compile(export_all).
> -record(rec1, {fred}).
> -record(rec2, {harry}).
> test() ->
>     #rec2{} = do_something(1, fun map/1).
> do_something(Num, MapFun) ->
>     MapFun(Num).
> map(_X) ->
>     #rec1{}.
> If I run Dialyzer against it, I get no errors or warnings logged, even
> though it's quite apparent that it will fail.  I would have expected that
> Dialyzer could infer that the return type of do_something was the return
> type of MapFun;  within the context of do_something(), that is clearly
> any(), but within the context of test() I would have thought that it could
> see that do_something() is actually going to return a #rec1{} record, that
> being the return type of map().
> If I replace the call to MapFun with a call to map(), as in:
> do_something(Num, _MapFun) ->
>     map(Num).
> Then everything works as expected - Dialyzer correctly tells me that my code
> is broken.  Is there anything I can do to "teach" dialyzer how to interpret
> the MapFun?  It works as I would like with functions such as lists:map():
> -module(test).
> -compile(export_all).
> -record(rec1, {fred}).
> -record(rec2, {harry}).
> test() ->
>     [#rec2{}] = lists:map(fun map/1, [1]).
> map(_X) ->
>     #rec1{}.
> With the above, I get the expected warning.  I've looked at lists.erl, and
> it doesn't look to be doing anything different.  It does have some -spec
> directives, but adding those in my code did not appear to help.
> Any hints?
> Cheers,
> Steve
> --
> Steve Strong
> @srstrong
> Sent with Sparrow
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://erlang.org/mailman/listinfo/erlang-questions
>
>



More information about the erlang-questions mailing list