Erlang 为什么';透析器是否检测到这种不良类型?
在这种情况下,透析器的行为对我来说相当奇怪,我还没有找到更好的理解它的方法 这不是一个错误:Erlang 为什么';透析器是否检测到这种不良类型?,erlang,elixir,dialyzer,Erlang,Elixir,Dialyzer,在这种情况下,透析器的行为对我来说相当奇怪,我还没有找到更好的理解它的方法 这不是一个错误: 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 < 1
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
defmodule Blog.UserResolver do
@键入one_user::({:error,String.t})
@spec find(%{id:String.t},any())::一个用户
def find(%{id:id},_info)do
年龄=:标准兰特(99)
如果(年龄<100岁)做什么
#这不会触发类型错误,即使它是错误的
{:好的,%{电子邮件:dw@1g.io,名称:“Deedub”}
其他的
{:错误,“年龄不在正确的范围内”}
结束
结束
结束
请注意,其中一个可能的返回分支肯定与类型签名不匹配
但是,这确实有一个错误:
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
defmodule Blog.UserResolver do
@键入one_user::({:error,String.t})
@spec find(%{id:String.t},any())::一个用户
#由于没有与类型规范匹配的返回路径,因此引发错误
def find(%{id:id},_info)do
年龄=:标准兰特(99)
如果(年龄<100岁)做什么
{:好的,%{电子邮件:dw@1g.io,名称:“Deedub”}
其他的
10
结束
结束
结束
在这种情况下,所有可能的分支都与typespec不匹配,透析器显示有以下错误消息:
web/blog/user\u resolver.ex:4:函数'Elixir.blog.UserResolver'的类型规范无效:find/2。成功的键入是(#{'id':==u,=>},)->10 |{'ok',#{'email':=,'name':=}
我不理解的部分是透析器清楚地识别出分支可能返回的两种不同类型(()({'id':={uuu,{u=>},{u>},})->10{'ok',{'email':=,'name':=}/code>),所以这不是推断的问题。那么为什么它不识别出其中一个分支不符合类型规范呢(如果只有一个分支符合,这似乎很高兴,这根本不是我想要的)从Dogbert提供的链接来看,透析器将:
只抱怨会导致崩溃的类型错误
在第一个示例中,如果age始终大于或等于100,则函数将返回声明的类型。在第二个示例中,函数无法返回声明的类型
dialyzer
创建了一组约束方程。如果这些方程有任何解决方案,那么dialyzer不会抱怨。Erlang是作为一种动态类型语言创建的。dialyzer
只是一个事后编写的程序。我相信,出于他们深思熟虑、讨论和理论化的原因,设计师许多透析器选择了这种功能
我正在寻找一个更严格的类型检查,如果可能的话
目前不可能:
Erlang类型系统
没有更精细的字体系统的原因是
Erlang的发明家们知道如何写一个,所以从来没有完成过
静态类型系统的优点是可以在任何时间预测错误
编译时而不是运行时,因此允许在
更早发现并以更低的成本修复。许多人
尝试为Erlang构建静态类型系统。不幸的是,由于
Erlang发明时做出的设计决策,目前还没有任何项目
能够编写全面的类型系统,因为具有热代码
加载,这本质上是困难的
在众多类型的系统火焰战中,“看起来应该是这样的
“简单”-事实上,几周的编程可以使一个类型系统
处理95%的语言。几年的工作[由一些
计算机科学界最聪明的人]已经开始尝试解决这个问题
其他5%——但这真的很难。”
来自“Erlang编程(Francesco Cesarini&Simon Thompson)”
控制动态类型程序需要一个测试套件
。Elixir只是Erlang的一个Rubified版本。Ruby也是一种动态类型语言,但它没有透析器。Ruby唯一的功能就是测试。你使用测试套件来控制计算机编程语言的狂野西部,而不是编译器。如果您需要静态类型的语言,那么Erlang的Rubified版本不是一个好的选择——请参阅Haskell。我认为这里的“成功类型”部分解释了这一点:。“请记住,透析器是乐观的。它对您的代码有象征性的信任,并且因为有可能在某个点上转换/1的函数调用成功,透析器将保持沉默。在这种情况下,不会报告类型错误。”。“但这似乎不直观-在错误消息中,它显然可以检测到每种可能的返回类型。也许这只是我可以设置的一个标志,上面写着,“如果其中一个分支与类型规范不匹配,请告诉我”?如果可能的话,我正在寻找一个更严格的类型检查器,如果必要的话,我很乐意接受额外的挑战。你可以这样看:如果类型规范能够成功,透析器将不会报告任何错误,因为不完整的定义是故意的。在你的第一个例子中,你可以想象正常的(并记录在案的)函数的行为是返回{:error,String.t}
(不是很奇怪),其他情况不应该发生