Erlang类型规范 #
一、类型规范概述 #
Erlang类型规范用于描述函数和数据的类型,配合Dialyzer进行静态分析。
二、基本类型 #
2.1 内置类型 #
| 类型 | 说明 |
|---|---|
any() |
任意类型 |
none() |
无类型 |
pid() |
进程标识符 |
port() |
端口 |
reference() |
引用 |
atom() |
原子 |
binary() |
二进制 |
integer() |
整数 |
float() |
浮点数 |
number() |
数字 |
list() |
列表 |
tuple() |
元组 |
map() |
映射 |
string() |
字符串 |
boolean() |
布尔值 |
function() |
函数 |
term() |
任意项 |
2.2 类型定义 #
erlang
-module(type_definition).
-export_type([user/0, result/0]).
-type user() :: #{name => string(), age => non_neg_integer()}.
-type result() :: {ok, term()} | {error, term()}.
三、函数规范 #
3.1 基本语法 #
erlang
-spec function_name(ParamType1, ParamType2, ...) -> ReturnType.
3.2 使用示例 #
erlang
-module(spec_example).
-export([add/2, divide/2, process/1]).
-spec add(number(), number()) -> number().
add(A, B) -> A + B.
-spec divide(number(), number()) -> {ok, number()} | {error, division_by_zero}.
divide(_, 0) -> {error, division_by_zero};
divide(A, B) -> {ok, A / B}.
-spec process(term()) -> {ok, term()} | {error, term()}.
process(Data) -> {ok, Data}.
3.3 多子句规范 #
erlang
-module(multi_clause_spec).
-export([handle/1]).
-spec handle({request, term()}) -> {response, term()};
({error, term()}) -> {error, term()}.
handle({request, Data}) -> {response, Data};
handle({error, Reason}) -> {error, Reason}.
四、自定义类型 #
4.1 type定义 #
erlang
-module(custom_type).
-export_type([user_id/0, user/0, status/0]).
-type user_id() :: pos_integer().
-type status() :: active | inactive | pending.
-type user() :: #{id => user_id(), name => string(), status => status()}.
4.2 opaque类型 #
erlang
-module(opaque_type).
-export_type([handle/0]).
-export([new/0, get_value/1]).
-opaque handle() :: {handle, reference(), term()}.
-spec new() -> handle().
new() -> {handle, make_ref(), undefined}.
-spec get_value(handle()) -> term().
get_value({handle, _, Value}) -> Value.
opaque类型对外隐藏内部结构。
五、Dialyzer #
5.1 构建PLT #
bash
dialyzer --build_plt --apps erts kernel stdlib
5.2 分析模块 #
bash
dialyzer my_module.erl
5.3 分析项目 #
bash
dialyzer --src src/
5.4 使用Rebar3 #
bash
rebar3 dialyzer
六、常见警告 #
6.1 类型不匹配 #
erlang
-spec add(integer(), integer()) -> integer().
add(A, B) -> A + B.
demo() ->
add(1.0, 2.0).
6.2 无用代码 #
erlang
func(X) ->
Y = X + 1,
X.
6.3 模式匹配覆盖 #
erlang
classify(0) -> zero;
classify(N) when N > 0 -> positive;
classify(N) when N < 0 -> negative;
classify(0) -> duplicate.
七、最佳实践 #
7.1 为公共API添加规范 #
erlang
-module(public_api).
-export([create/1, read/1, update/2, delete/1]).
-spec create(map()) -> {ok, term()} | {error, term()}.
create(Data) -> {ok, Data}.
-spec read(term()) -> {ok, term()} | {error, not_found}.
read(Id) -> {ok, #{id => Id}}.
-spec update(term(), map()) -> {ok, term()} | {error, term()}.
update(Id, Data) -> {ok, #{id => Id, data => Data}}.
-spec delete(term()) -> ok | {error, term()}.
delete(_Id) -> ok.
7.2 使用有意义的类型名 #
erlang
-type user_id() :: pos_integer().
-type email() :: binary().
-type timestamp() :: non_neg_integer().
八、总结 #
本章学习了:
- 基本类型
- 类型定义
- 函数规范
- 自定义类型
- Dialyzer使用
- 最佳实践
最后更新:2026-03-27