自动向顶级函数添加类型签名
我很懒,编写了一个 Haskell 模块(使用优秀的 EclipseFP IDE),而没有为我的顶级函数提供类型签名。
EclipseFP 使用 HLint 自动标记每个有问题的函数,我只需单击 4 次鼠标即可修复每个函数。有效,但乏味。
是否有一个实用程序可以扫描 .hs 文件,并发出一个修改版本,为每个顶级函数添加类型签名?
示例:
./addTypeSignatures Foo.hs
将读取文件 Foo.hs:
foo x = foo + a
则会发出奖励积分
foo :: Num a => a -> a
foo x = x + 1
如果该工具自动编辑 Foo.hs
并保存备份 Foo.bak.hs
,
I was lazy and wrote a Haskell module (using the excellent EclipseFP IDE) without giving type signatures to my top-level functions.
EclipseFP uses HLint to automatically label every offending function, and I can fix each one with 4 mouse clicks. Effective, but tedious.
Is there a utility program that will scan a .hs file, and emit a modified version that adds type signatures to each top-level function?
Example:
./addTypeSignatures Foo.hs
would read a file Foo.hs
:
foo x = foo + a
and emit
foo :: Num a => a -> a
foo x = x + 1
Bonus points if the tool automatically edits Foo.hs
in place and saves a backup Foo.bak.hs
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
emacs 的 haskell 模式有一个插入函数类型签名的快捷方式:Cu、Cc、Ct。它不是自动的,您必须为每个功能执行此操作。但如果您只有一个模块,那么您可能需要几分钟的时间才能完成它。
There's haskell-mode for emacs that has a shortcut to insert type signature of a function: C-u, C-c, C-t. It is not automatic, you have to do it for each function. But if you have only one module, it will probably take you a few minutes to go through it.
根据 ehird 的评论,这是上述脚本的变体,它使用“:browse”而不是“:type”。
此解决方案的一个主要问题是“:browse”显示完全限定的类型名称,而“:type”使用导入的(缩写的)类型名称。如果您的模块使用不合格的导入类型(常见情况),则该脚本的输出将编译失败。
这个缺点是可以修复的(使用一些导入解析),但是这个兔子洞越来越深。
Here's a variation of the above script, that uses ":browse" instead of ":type", per ehird's comment.
One major problem with this solution is that ":browse" displays fully qualified type names, whereas ":type" uses the imported (abbreviated) type names. This, if your module uses unqualified imported types (a common case), the output of this script will fail compilation.
That shortoming is fixable (using some parsing of imports), but this rabbit hole is getting deep.
这是另一个基于解析 GHC
-Wmissing-signatures
警告的黑客尝试,因此脚本不必解析 Haskell。它将警告转换为 sed 脚本,该脚本执行插入并将其结果打印到 stdout,或者如果给出-i
则就地修改文件。需要如下配置的 Stack 项目,但您可以更改
buildCmd
。适用于我在 GHC 8.2.2 和 8.4.3 上尝试过的几个文件,但与 @misterbee 的第一个答案中的警告相同:) 另外,如果旧的或新的 GHC 产生不同格式的警告,它显然会与旧的或新的 GHC 发生冲突(但是对我来说,更复杂的工具似乎也总是会损坏,所以......)。
Here's another hacky attempt based on parsing GHC
-Wmissing-signatures
warnings, so the script doesn't have to parse Haskell. It transforms the warnings into a sed script that does the insertions and prints its result to stdout, or modifies the file inplace if-i
is given.Requires a Stack project as configured below, but you can change the
buildCmd
.Works on the few files I tried it on with GHC 8.2.2 and 8.4.3, but same warnings as in @misterbee's first answer apply :) Also, it will obviously break with older or newer GHCs if they produce differently formatted warnings (but for me, the more sophisticated tooling seem to break all the time too, so...).
这个 perl 脚本做了一些修改,对源文件结构做出了一些假设。 (例如:
.hs
文件(而不是.lhs
),签名位于定义之前的行上,定义与左边距齐平,等等)它尝试处理(跳过)注释、方程式定义(具有重复的左侧)以及在 ghci 中生成多行输出的类型。
毫无疑问,许多有趣的有效案例没有得到妥善处理。该脚本与 Haskell 的实际语法相差甚远。
它非常慢,因为它为每个需要签名的函数启动一个 ghci 会话。
它创建一个备份文件
File.hs.bak
,将找到的函数打印到 stderr,以及缺少签名的函数的签名,并将升级后的源代码写入File.hs.它使用中间文件
File.hs.new
,并进行一些安全检查以避免用垃圾覆盖您的内容。使用风险由您自行承担。
该脚本可能会格式化您的硬盘、烧毁您的房屋、不安全的PerformIO 以及其他不纯的副作用。事实上,可能会的。
我感觉很肮脏。
使用我自己的几个
.hs
源文件在 Mac OS X 10.6 Snow Leopard 上进行了测试。This perl script does a hack job at it, making some assumptions about source file structure. (Such as:
.hs
file (not.lhs
), signatures are on the line immediately preceding definitions, definitions are flush on the left margin, etc)It tries to handle (skip over) comments, equation-style definitions (with repeated left-hand-sides), and types that generate multi-line output in
ghci
.No doubt, many interesting valid cases are not handled properly. The script isn't close to respecting the actual syntax of Haskell.
It is incredibly slow, as it launches a
ghci
session for each function that needs a signature.It makes a backup file
File.hs.bak
, prints the functions it finds to stderr, as well as signatures for functions missing signatures, and writes the upgraded source code toFile.hs
. It uses an intermediate fileFile.hs.new
, and has a few safety checks to avoid overwriting your content with garbage.USE AT YOUR OWN RISK.
This script might format your hard drive, burn your house down, unsafePerformIO, and have other impure side effects. In fact, it probably will.
I feel so dirty.
Tested on Mac OS X 10.6 Snow Leopard with a couple of my own
.hs
source files.对于 Atom 编辑器,可以使用 haskell-ghc-mod 包自动插入每个函数的类型签名,该包提供:
https://atom.io/packages/haskell-ghc-mod#keybindings
For the Atom Editor its possible to automatically insert the type signature per function with the package haskell-ghc-mod which provides:
https://atom.io/packages/haskell-ghc-mod#keybindings