Haskell 使GHC忽略不在范围内的错误
我正在构建一个模块,每次我编写一个函数时,它都会调用十几个还不存在的函数。显然,它们最终会存在,但在我完成代码编写之前能够进行语法检查将是一件好事 对于“nameHaskell 使GHC忽略不在范围内的错误,haskell,ghc,Haskell,Ghc,我正在构建一个模块,每次我编写一个函数时,它都会调用十几个还不存在的函数。显然,它们最终会存在,但在我完成代码编写之前能够进行语法检查将是一件好事 对于“namefoo不在范围内”,是否有一些标志组合可用于使GHC发出警告而不是错误 (如果GHC可以为不存在的名称选择一个类型签名,并确认程序仍然可以进行类型检查,那就太好了。这几乎就是“类型孔”功能所做的——但要使用它,您仍然必须手动定义所有标识符。)使用命名的类型孔: > let f x = _g . _h x $ x Found
foo
不在范围内”,是否有一些标志组合可用于使GHC发出警告而不是错误
(如果GHC可以为不存在的名称选择一个类型签名,并确认程序仍然可以进行类型检查,那就太好了。这几乎就是“类型孔”功能所做的——但要使用它,您仍然必须手动定义所有标识符。)使用命名的
类型孔:
> let f x = _g . _h x $ x
Found hole ‘_g’ with type: b0 -> c
Where: ‘b0’ is an ambiguous type variable
‘c’ is a rigid type variable bound by
the inferred type of f :: s -> c at <interactive>:2:5
Relevant bindings include
x :: s (bound at <interactive>:2:7)
f :: s -> c (bound at <interactive>:2:5)
In the first argument of ‘(.)’, namely ‘_g’
In the expression: _g . _h x
In the expression: _g . _h x $ x
Found hole ‘_h’ with type: s -> s -> b0
Where: ‘b0’ is an ambiguous type variable
‘s’ is a rigid type variable bound by
the inferred type of f :: s -> c at <interactive>:2:5
Relevant bindings include
x :: s (bound at <interactive>:2:7)
f :: s -> c (bound at <interactive>:2:5)
In the expression: _h
In the second argument of ‘(.)’, namely ‘_h x’
In the expression: _g . _h x
>让fx=\u g_h x$x
发现类型为b0->c的孔“\g”
其中:“b0”是一个不明确的类型变量
“c”是一个刚性类型变量,由
f::s->c的推断类型:2:5
相关绑定包括
x::s(绑定时间:2:7)
f::s->c(绑定时间:2:5)
在“(.”的第一个参数中,即“_g”
在表达式中:_g_hx
在表达式中:_g_h x$x
找到类型为s->s->b0的孔“\u h”
其中:“b0”是一个不明确的类型变量
“s”是一个刚性类型变量,由
f::s->c的推断类型:2:5
相关绑定包括
x::s(绑定时间:2:7)
f::s->c(绑定时间:2:5)
在表达式中:
在“(.”的第二个参数中,即“hx”
在表达式中:_g_hx
因此,这将为您提供\u g::b0->c
和\u h::s->s->b0
,上下文为x::s
和f::s->c
。类型检查器大部分时间都可以推断出这些类型(这是TypedHoles
的要点),您可以给它们命名。如果需要,可以将所有函数定义为符号名称的第一个字符\u
,然后使用编辑器将\u(+)\b
替换为\1
。如果您想绕过镜头惯例,即对记录字段使用\u name
,则只需在孔名称上加2个下划线即可
这仍然会阻止您的代码编译,但是如果您将其与-fdefer类型错误
结合使用,它们将被报告为警告,从而允许您的类型错误在运行时发生。我通常的方法是将缺少的函数或值定义为未定义的
。它很容易定义,并且给您留下了一个方便的标记,表明所讨论的函数尚未定义
我知道这并不能回答OP的问题,因为函数仍然需要手工定义,但我认为它可能会很有用。我敢说,对于这样的函数,写下签名和一个=未定义的,这是一个很好的做法。。。但是,好问题,我有时也希望,对于如此奇怪的想法,我不确定是否值得尝试让它们进行类型检查,因为它甚至可能不进行语法分析。另一种检查语法是否正确的方法是使用类似于无点
的东西并检查“parse error:EOF”,但是这使得除了一个单行表达式之外,做任何事情都很困难。@leftaroundabout在我的例子中,我正在构建一个解析器。这意味着有数百个不存在的标识符,所有这些标识符都应该是解析器。当我最终写完所有的作品时,它应该会起作用。但是在我结束之前捕获语法错误会很好…我将继续@leftaroundabout的类型签名+未定义方法。我一直在用它。如果您愿意,您甚至可以跳过类型签名,让变量完全多态,但您可以添加的类型签名越多,类型错误消息可能就越好。@leftaroundabout我假设OP实际上是指“语法和类型检查”。如果您真的只想进行语法检查,则不需要定义所有内容-范围外错误意味着模块必须首先正确解析。因此,您的意思是,如果我用下划线启动所有标识符并启用-fdefer type errors
,我将大致获得我想要的行为?@MathematicalOrchid,如果我明白你想要什么。您的标识符只需以
开头就可以使其成为一个洞,GHC推断出该洞的类型,GHC通常会为其发出编译错误,但-fdefer type errors
会将这些错误转化为警告,这样您甚至可以运行程序直到出现洞为止,所以让f=putstrn“test”>\u foo;f
将打印测试
,然后显示一个异常,该异常包含编译时您将获得的准确错误消息,而不会出现-fdefer类型错误
@MathematicalOrchid,正如dfeuer和leftaroundaound所指出的那样,使用类型签名和undefined
定义它们不需要编译任何额外的标志,这将改进错误消息,并确保表达式具有所需的类型,而不是进行类型检查所需的任何类型。我想你可以为它编写一个插件,可以用错误“hole name”
和推断的类型签名从表达式中提取一个命名的洞,然后用“extract all”命令将这些洞分解出来就轻而易举了。