Erlang 从超类型中排除类型

Erlang exclude type from supertype

在 Erlang 中,是否可以通过从超类型中排除子类型来定义类型?例如,我将如何定义一个“除 pid() 之外的任何类型”的类型:

-type anything_but_pid() :: ...?

阅读有关主管数据类型的文档,我遇到了 this type spec for child_id(),它将类型定义为 term(),然后说 Not a pid()下面的评论:

child_id() = term()

Not a pid().

如果我不想明确列出所有可能的类型,这是我能做的最好的事情吗?

作为一个可能的解决方法,您可以像这样为您的函数定义一个规范:

    -spec foo(pid()) -> ...;
             (any()) -> ...
    foo(data) when is_pid(data) -> error;
    foo(data) -> ....

特别是 anything_but_pid(),您可以“简单地”枚举所有其他选项:

-type anything_but_pid() :: port()
                          | reference()
                          | atom()
                          | bitstring()
                          | number()
                          | fun()
                          | maybe_improper_list()
                          | map()
                          | tuple()

当然,这并不能一概而论...

不,从 OTP 23(甚至 24)开始,这不受支持。

此外,在这种情况下期望 Dialyzer 提供帮助是不明智的,因为 Dialyzer 通常过于逼近,出于多种原因,尽管我认为它不会将这种类型转变为 term() 立即,它很可能会在第一个给定的机会时这样做(例如,无论您在哪里调用这样的函数)。