是否应该为主函数指定类型签名?为什么或为什么不?

14

我从《Learn You A Haskell For Great Good》的第9章中学到,按照惯例,我们通常不会为main指定类型声明。

据我所知,这种惯例很普遍。但是,如果我编译一个缺少对main类型签名的程序,例如

-- test.hs

-- main :: IO ()
main = print (1 :: Int)

GHC会发出警告:

$ ghc -Wall test.hs
[1 of 1] Compiling Main             ( test.hs, test.o )

test.hs:2:1: Warning:
    Top-level binding with no type signature: main :: IO ()
Linking test ...
$

我很困惑... 如果main的类型签名确实是多余的,为什么没有它会导致GHC在缺失时发出警告?除了消除警告之外,是否还有指定main类型的好理由?


缺少顶层类型签名应该是一个错误。事实上,它应该是非法的。 - Shoe
5
应被视为犯罪而受到惩罚,这里的“illegal”指的是行为不当,而非语言用法上的不合规。 - Shoe
1
特别是顶级导出类型签名可能是一个错误。我使用很多非导出的通用帮助程序,没有公共文档,它们的签名比它们的主体还长。写这些完全没有帮助,只是一种烦恼。 - Bartek Banachewicz
2
这本书只是在说明他们不会为 main 提供类型注释,以减少演示中的混乱。他们并没有暗示您不应该对其进行注释。 - chi
1
有趣的是,我没有以那种方式阅读它。虽然我不确定该句话应该如何解释。这是另一个含糊不清的“我们”的例子。 - jub0bs
我也有这样的印象,即该句是在谈论书中使用的惯例,而不是 Haskell 社区的一般情况。个人认为,在实践中给 main 指定一个明确的类型签名非常有用。 - shang
2个回答

15

总的来说,正如那个警告所表明的那样,给顶层绑定指定类型是一种 始终 都是一个好主意。事实上,更合理的说法是:

按照惯例,我们为所有1都指定类型声明。

当然,在一个大项目中,main本身构成了可忽略的工作量,因此省略签名真的没有任何意义。为了保持一致,请写出它。

然而,尽管Haskell非常适合结构良好的项目,并且实际上有一种倾向于在 中编写几乎所有的东西,它也出人意料地适用于快速脚本编写,其它人可能会用Python或Perl编写。在这些情况下,您通常不太关心安全性和良好的文档等问题,您只是想快速编写尽可能简洁的代码来完成工作。通常您不会使用-Wall编译这些脚本,而只是使用runhaskell执行它们。由于脚本始终需要包含一个 main(与大多数其他Haskell源文件不同),因此在这里省略签名确实是明智的选择。

我仍然怀疑大多数Haskeller现在甚至在最简单的脚本中也会写出main::IO(),只是出于习惯。


1仅适用于所有顶层的绑定。局部签名有时也有意义,但通常会使代码变得混乱。


感谢您的澄清。 - jub0bs
对于更大的项目,启用-fwarn-missing-signatures-Werror是有意义的,这将强制main具有类型签名。 - Petr
1
@PetrPudlák 我通常与 -Werror 一起使用 -Wall(我相信这会启用 -fwarn-missing-signatures)。 - jub0bs

8
实际上,为 main 编写类型签名是一个非常好的主意,因为如果你试图使用点-自由形式编写代码时过于繁琐,你最终会得到类型为 IO (IO ())main。虽然这是被接受的(语言标准规定 main 必须具有某种形式为 IO a 的类型),但是 main 的“内部 IO 操作”将被丢弃,这几乎肯定不是你想要的结果(你可能希望使用 join 函数)。

有趣。你能否添加一个链接,指出在标准中你读到 main 只需要具有 IO a 形式的某种类型 - jub0bs
@Jubobs:请参见https://www.haskell.org/onlinereport/haskell2010/haskellch5.html#x11-980005的第二段。 - Reid Barton
4
我认为不要求 main :: IO () 是标准的一个(非常)小缺陷。然而,这是个人口味的问题。 - chi
你能否添加一个这样的示例,当 mainIO (IO a) 结束时? - Petr
一个人造的例子:main = return getLine,它的类型是 IO (IO String) - jub0bs
或者稍微不那么牵强的写法是 main = putStrLn <$> getLine - Reid Barton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接