在这种情况下,透析对我来说很奇怪,我还没有找到任何更好地理解它的东西。
这不是错误:
defmodule Blog.UserResolver do
@type one_user :: ( {:error, String.t} )
@spec find(%{id: String.t}, any()) :: one_user
def find(%{id: id}, _info) do
age = :rand.uniform(99)
if (age < 100) do
# This doesn't trigger a type error, even though it's wrong
{:ok, %{email: "dw@1g.io", name: "Deedub"}}
else
{:error, "Age isn't in the right range"}
end
end
end
请注意,可能的返回分支之一肯定与类型签名不匹配。
但是,这确实有一个错误:
defmodule Blog.UserResolver do
@type one_user :: ( {:error, String.t} )
@spec find(%{id: String.t}, any()) :: one_user
# Throws an error since no return path matches the type spec
def find(%{id: id}, _info) do
age = :rand.uniform(99)
if (age < 100) do
{:ok, %{email: "dw@1g.io", name: "Deedub"}}
else
10
end
end
end
在这种情况下,可能的分支的无与Typespec匹配,透明师说有此错误消息:
web/blog/user_resolver.ex:4: Invalid type specification for function 'Elixir.Blog.UserResolver':find/2. The success typing is (#{'id':=_, _=>_},_) -> 10 | {'ok',#{'email':=<<_:64>>, 'name':=<<_:48>>}}
我不明白的一部分是透明师明显识别分支可能返回的两种不同类型((#{'id':=_, _=>_},_) -> 10 | {'ok',#{'email':=<<_:64>>, 'name':=<<_:48>>}
(,因此这不是推论的问题。那么,为什么它不认识到其中一个分支不符合类型规格(如果只有一个分支的一个,这似乎很高兴,这根本不是我想要的(
来自Dogbert提供的学习链接,dialyzer
将:
仅抱怨可以保证崩溃的类型错误。
在您的第一个示例中,如果年龄总是大于或等于100,则您的功能将返回声明的类型。在第二个示例中,您的函数无法返回声明的类型。
dialyzer
创建一组约束方程。如果对这些方程式有任何解决方案,那么透明师就不会抱怨。Erlang是作为动态键入语言而创建的。dialyzer
只是某人在事实之后写的程序。出于原因,我敢肯定他们在思考并讨论和理论上了,透析的设计师选择了该功能。
如果可能的话,我正在寻找更严格的类型检查器。
到目前为止不可能:
ERLANG类型系统
没有更精细类型系统的原因是 Erlang发明家知道如何写一个,因此从未完成。这 静态类型系统的优势是可以预测错误 编译时间而不是在运行时,因此允许故障 以较低的成本检测到较早的固定。许多人有 试图为Erlang构建静态类型系统。不幸的是,由于 当Erlang发明时做出的设计决定,没有任何项目 能够编写综合类型系统,因为使用热代码 加载,这本质上是困难的。引用乔·阿姆斯特朗 众多类型的系统火焰战争之一,"似乎应该是 "容易" - 确实,几周的编程可以制造一种类型的系统 处理95%的语言。几个男子的工作 在计算机科学中最聪明的头脑]试图修复 其他5% - 但这确实很困难。"
来自" Erlang编程(Francesco cesarini&amp; Simon Thompson("。
需要test suite
才能控制动态键入程序。长生不老药只是Erlang的摩擦版本。Ruby也是一种动态键入的语言,但它没有透明度。Ruby唯一的事情就是测试。您可以使用测试套件将计算机编程语言的野外西部控制在控制之下,而不是编译器。如果您需要一种静态键入的语言,那么Erlang的磨难版本不是一个不错的选择 - 请参阅Haskell。