В качестве побочного эффекта сообщения об ошибке в списке ошибок erlang, я получил подробный ответ на этот вопрос от Костиса Сагонаса, изобретателя диализатора и typer.
На мой дополнительный вопрос я получил следующий отличный иподробный ответ:
На Солнце, 1 мая 2011 года в 17:53, Костис Сагонас написал:
Пир Стрицингер написал:
Кстати: нормально ли не получать никаких предупреждений, когда просто выполняешь --annotate в typer, а затем в диализаторе без подправленных вручную спецификаций
Да.На самом деле, typer - это просто интерфейс для определения базового типа диализатора (т. Е. Без компонента идентификации предупреждения).
IMO, в этом нет особого смысла, если вы не собираетесь вручную "массировать"спецификации, которые вы получаете и предоставляете больше информации для некоторых из них.Посмотрите на вашу предыдущую программу.Тот факт, что два типа << <em>: 64, : _ * 8 >> ссылаются на одно и то же количество, может быть лучше выражен, если вы введете тип, как в:
-type packet() :: <<_:64,_:_*8>>,
Аналогично для канала:
-type channel() :: atom() | pid() |{atom(),_}.
, и тогда спецификация будет выглядеть лучше.Кроме того, у dialyzer / typer нет информации о том, какой тип веселья вы собираетесь использовать во втором аргументе функции recv/3
, но вы это делаете!Из кода видно, что для этого требуется запись #can_pkt{}
, так почему бы вам не добавить соответствующие поля к ее полям и не ввести тип для них?
-record(can_pkt, {id :: id(), data :: binary(), timestamp :: ts()}).
-type can_pkt() :: #can_pkt{}.
, тогда спецификации могут выглядеть намного лучше:
-spec recv(packet(), fun((can_pkt()) -> R), channel()) -> R.
-spec decode(packet()) -> can_pkt().
и обратите внимание, что я использовал переменную типа заполнителя R
для обозначения того факта, что функция recv/2
возвращает любой тип, который возвращает fun во втором аргументе.Вы, вероятно, знаете, что это за тип, поэтому вам также следует ввести для него тип и использовать его собственное имя.
Надеюсь, это поможет,
Kostis
PS.Жаль, что вы опубликовали это в erlang-bugs, поскольку информация, содержащаяся в приведенном выше, является IMO более интересной, чем фактическая ошибка.
Поскольку он ссылается на фрагмент кода, я включил его в свой отчет об ошибкахЯ включаю это здесь.Следующий фрагмент кода был автоматически помечен typer --annotate
:
-record(can_pkt, {id, data, timestamp}).
-spec recv(<<_:64,_:_*8>>,fun((_) ->
any()),atom() | pid() | {atom(),_}) -> any().
recv(Packet, Recv_fun, Chan) ->
P = decode(Packet),
#can_pkt{id=Can_id, data=Can_data}=P,
Recv_fun(P).
-spec decode(<<_:64,_:_*8>>) ->
#can_pkt{id::<<_:11>>,data::binary(),timestamp::char()}.
decode(<<_:12, Len:4, Timestamp:16,
0:3, Id:11/bitstring, 0:18,
Data:Len/binary, _/binary>>) ->
#can_pkt{id=Id, data=Data, timestamp=Timestamp}.