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