由於二郎山 - 錯誤列表報告bug的副作用,我得到了一個詳細的回答這個從Kostis Sagonas ,透析器和typer的發明者。
我這邊的問題,我得到了下面的偉大和詳細的解答:
On Sun, May 1, 2011 at 5:53 PM, Kostis Sagonas wrote:
同行Stritzinger寫道:
BTW:這是正常的不只是當得到任何警告做 - annotate typer然後透析器沒有手動調整規範
是的。事實上,typer只是透析器基本類型推斷的前端(即沒有警告識別組件)。
IMO,如果您不打算手動「按摩」您獲得的規格併爲其中的某些規格提供更多信息,那麼這樣做的意義非常小。看看你以前的計劃。事實上,這兩個< < :64,:_ * 8 >>類型是指相同的量可以表示更好,如果你推出了一款型號爲:
-type packet() :: <<_:64,_:_*8>>,
同樣,對於渠道:
-type channel() :: atom() | pid() |{atom(),_}.
然後規範已經看起來更好了。此外,透析器/ 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
回報的事實任何類型的樂趣在它的第二個參數回報。你可能知道這個類型是什麼,所以你也應該爲它引入一個類型並使用它的專有名稱。
希望這有助於
Kostis
PS。很遺憾你在erlang-bug中發佈了這個消息,因爲上面所包含的信息比實際的bug更有趣。
由於他提到了一個代碼片段,我將它包含在我的bug報告中,我將它包含在這裏。以下代碼片段被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}.