为啥这个带有类型签名的 erlang prog 可以编译?

Posted

技术标签:

【中文标题】为啥这个带有类型签名的 erlang prog 可以编译?【英文标题】:Why this erlang prog with type signature can compile?为什么这个带有类型签名的 erlang prog 可以编译? 【发布时间】:2022-01-03 13:03:09 【问题描述】:

我有这个程序:

-module(a).
-export([add/2]).
-export([add2/1]).

-spec add(integer(),integer())->integer().
add(A,B)->A+B.

add2(C)->C+add(1,"a").

我可以毫无错误地编译这个 prog。但我认为我应该得到该行的错误

add(1,"a").

在任何静态类型语言中,它都无法编译,那么为什么erlang会编译它呢?如何 编写类型签名以便 erlang 可以捕获此错误?如果 erlang 不能,elixir 可以编写相同的 prog 但可以捕获此错误吗?谢谢!

【问题讨论】:

【参考方案1】:

Erlang 不是静态类型语言,它是总是动态类型的。在编译过程中你无法捕捉到它,因为 erlc 根本不关心 -spec。它仅用于文档,Dialyzer(从技术上讲是外部工具)可以使用它对合约进行一些(有限的)静态分析。

关于如何使用 Dialyzer,请查看:

Documentation of Dialyzer application Rebar3 Dialyzer task documentation erlang.mk Dialyzer guide

【讨论】:

【参考方案2】:

Erlang 编译器不检查类型规范。您可以使用 Erlang 中包含的 Dialyzer 来检查它们:

dialyzer --src a.erl

它给出以下输出:

  Proceeding with analysis...
a.erl:8: Function add2/1 has no local return
a.erl:8: The call a:add
         (1,
          "a") will never return since the success typing is 
         (number(),
          number()) -> 
          number() and the contract is 
          (integer(), integer()) -> integer()
 done in 0m0.19s
done (warnings were emitted)

第一次运行 Dialyzer 时,它会抱怨它没有标准应用程序的 PLT(持久查找表)。您可以使用以下方式构建它:

dialyzer --build_plt --apps erts kernel stdlib mnesia

【讨论】:

以上是关于为啥这个带有类型签名的 erlang prog 可以编译?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Haskell 没有在函数签名中推断数据类型的类型类?

为啥 TypeScript 声称它“无法调用类型缺少调用签名的表达式”?

为啥我不能拥有带有此签名的 Q_PROPERTY?

Windows中 RabbitMQ安装与环境变量配置

Windows中 RabbitMQ安装与环境变量配置

从技术上讲,为啥 Erlang 中的进程比 OS 线程更高效?