在Erlang中可以使用多态记录吗?

时间:2017-09-27 14:12:51

标签: erlang

我正在阅读polymorphic types,唯一的例子是元组:

type queue(Type) :: {fifo, list(Type), list(Type)}.

我有这样的记录:

-record(heap_node, { item :: any(), children :: [#heap_node{}] }).
-type heap_node() :: #heap_node{}.

现在我无法将类型参数传递给记录。在Erlang中有可能吗?

2 个答案:

答案 0 :(得分:4)

您可以在item中创建一个多态的类型:

-type heap_node(A) :: #heap_node{item :: A}.

A不会延续到children字段 - 这些heap_node记录仍然会有一个不受限制的item字段。

我尝试递归使用该类型:

-type heap_node(A) :: #heap_node{item :: A, children :: [heap_node(A)]}.

但是Dialyzer并不喜欢这样:

dialyzer: Analysis failed with error:
foo.erl:9: Illegal declaration of #heap_node{children}

答案 1 :(得分:4)

-type queue(Type) :: {fifo, list(Type), list(Type)}.

您可能希望将其表示为:

-type queue(term()) :: {fifo, [term()], [term()]}.

这并不意味着这些是一致的条款。 term()any()的别名,只是意味着"您有一系列事物",而不是"同质事物列表"。

这里更重要的问题是问你要做什么?你想要达到的整体效果是什么? Erlang标准库具有大量数据结构,可以非常有效地处理队列,包,集合,集合,地图,树等等。

当然,您有特定需求的情况是您自己编写的。每当您有特定需求时,您会发现自己需要开放式类型(如term())或严格类型(如non_neg_integer()#{integer() := pid()})。

如果我们对您尝试实现的整体效果有了更多了解,那么可能会避免花费大量精力重新发明OTP或stdlib。

关于Erlang的哲学

请记住, Erlang不是一种学术语言。它是一种实用的工业语言,它受到学术概念的影响,因为它们是有效语言和系统设计的自然结果 - 在它创建的时代。

是:

  • 功能性 - 但这只是因为在编写大规模并发且无法用共享状态OOP进行推理的真实世界程序时,这是最有效的方法
  • 遵守"演员模型" - 但在该术语之前,因此不能说是"它的实施"。它看起来像一个actor模型,因为再一次,这是建模大规模并发系统并在流程中表示清晰分区的唯一理智方式。
  • Reactive - 但也早于该术语(应用于软件作为流行语)。这是使用消息传递模型的偶然结果。
  • 有一个类型系统 - 但后来成长为一种功能性语言的积极副作用。但它 a"纯粹"函数式语言,因为副作用是大多数程序编写的重点,而类型系统必须是弱,因为运行时处理动态调用和生成等等的方式。

(顺便提一下,您可能会想到的大多数其他热门流行语也恰好描述了Erlang,但这只是偶然的.Erlang恰好完全符合流行语,可能会持续几十年。)

这意味着Dialyzer是一个允许的 typer,而不是 strict typer - 它假设类型正确,直到它可以证明不是这样。严格的打字机是另一个方向,假设类型错误,除非它可以证明或推断否则。所以没有多态类型,因为程序中的所有内容都被假定为多态,直到类型约束可以通过分析通过类型语言显式推断出来。例如,你在Erlang类型系统中找不到与Haskell一样多的能力 - 但你会发现整个系统专门用于实现真实世界的程序,尽管你的思维方式可能在开发中有点不同。

另请参阅:dialyzer not detecting guard violation when function is exported