为什么透析器检测不到这种不良类型?



在这种情况下,透析对我来说很奇怪,我还没有找到任何更好地理解它的东西。

这不是错误:

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。

最新更新