6

In my progress of learning Elixir, I am playing around with Dialyzer to put types on my functions. In this regard, I've noticed that Dialyzer doesn't seem to check the types for anonymous functions.

In the example below, I am passing an anonymous function which adds two numbers and returns a number (t::number -> number), into the all? function. Thus I am not returning boolean as promised in the all? spec (t::any -> boolean).

defmodule Exercises do                                                                         
  @spec all?([t::any], (t::any -> boolean)) :: boolean                                         
  def all?([], _), do:  true                                                                   
  def all?([h|t], con) do                                                                      
    if con.(h) do                                                                              
      all?(t,con)                                                                              
    else                                                                                       
      false                                                                                    
    end                                                                                        
  end                                                                                          

  @spec funski() :: boolean                                                                    
  def funski() do                                                                              
    all?([1,1,2], &(&1 + 1))                                                                
  end
end

Dialyzer doesn't seem to report any errors or warnings for this code, and I am curios if Dialyzer is unable to check this kind of mistakes or if I am doing something wrong.

Michelrandahl
  • 3,365
  • 2
  • 26
  • 41

1 Answers1

2

It seems to be a Dialyzer bug. Calling :lists.all/2 (with the arguments swapped) produces the correct warning but for some reason calling your local all?/2 function with the same spec does not.

  • swapping the arguments of `all?/2` makes Dialyzer yield following warning `The call 'Elixir.Exercises':'all?'(fun((_) -> number()),[1 | 2,...]) will never return since the success typing is (maybe_improper_list(),any()) -> boolean() ...`. But I don't see how that relates to the analysis of the anonymous function `&(&1 + 1)` – Michelrandahl Jul 09 '15 at 13:04
  • I meant that when calling `:lists.all/2` (a completely different function) you should swap the arguments. And when calling that function you will get the correct warning. So it seems to be a bug in dialyzer that do not get the warning for your function. – Eric Meadows-Jönsson Jul 09 '15 at 13:57
  • ah sorry, I miss-read your answer. However, `:list.all(&(&1 + 1), [1,1,2])` doesn't make Dialyzer yield any warnings when I add it instead of the `all?([1,1,2]. &(&1 + 1))`.. Maybe it has something to do with the generated `.beam` code produced by the elixir compiler which I am feeding Dialyzer with... – Michelrandahl Jul 09 '15 at 14:19
  • 1
    `:lists.all/2` warns for me. I recommend using this project for running dialyzer: https://github.com/fishcakez/dialyze – Eric Meadows-Jönsson Jul 09 '15 at 18:42
  • nice tool, thank you. Now I get the warning as well (still no warning for the initial problem of course). – Michelrandahl Jul 10 '15 at 14:02