Piskator
Piskator

Reputation: 647

How to specify arguments and return types for functions within functions using the Erlang Dialyzer?

How do you specify arguments and return types type for functions within functions using the Erlang Dialyzer, such as functions from libraries or Behavior (e.g gen_servers gen_server:reply/2). For instance in the MVR code provided below, how can I specify that the maps:put/3 gets the right order of arguments, such that it's thrird argument is a map() ?

Furthermore is there a way to ensure it for variables within a function and/or globally, such that for instance an integer I declare within a function gets integer()?

-module(example_module).

-export([my_function/1, state_changer/3, test_function/0]).

-type map_arg() :: #{key1 => integer(), key2 => atom()}.
-type move() :: rock | paper | scissor.
-type playersmap() :: #{players => {pid(), pid()}} | #{players => {pid(), pid()}, fst_mover => {{pid(),_}, move()}}.


-spec my_function(Map_arg :: map_arg()) -> ok.

my_function(Map) ->
    ok.

test_function() ->
    CorrectMap = #{key1 => 1, key2 => 'value'},
    IncorrectMap = #{key1 => 1, key2 => 2},
    my_function(CorrectMap),
    my_function(IncorrectMap),
    state_changer({move, rock}, {self(), tag}, #{players  => {self(), self()}, fst_mover => {{self(), tag}, scissor}}).

-spec state_changer({move, Choice :: move()}, From :: {pid(), _}, PlayersMap :: playersmap()) -> {reply, playersmap()}.
state_changer({move, Choice}, From, PlayersMap) ->        
    {CurId, _} = From,    
    {P1Id, P2Id} = maps:get(players, PlayersMap),
    case CurId of
        P1Id ->                        
            PlayersMapNew = maps:put(fst_mover, {From, Choice}, PlayersMap),                    
            {reply, PlayersMapNew};
        P2Id -> 
            PlayersMapNew = maps:put(fst_mover, {From, Choice}, PlayersMap),                    
            {reply, PlayersMapNew}
    end.

EDIT

So far the only thing I have been able to come up with is some sort of wrapper around the functions that I would like to declare some type specificity for. Such as -spec my_maps_put(From :: reference(), Choice :: move(), PlayersMap :: playersmap())-> PlayersMapNew :: playersmap() , but I don't know if this is the best way.

Upvotes: 1

Views: 80

Answers (0)

Related Questions