Haskell:是什么让'main'与众不同?



使用此代码:

main :: FilePath -> FilePath -> IO ()
main wrPath rdPath = do x <- readFile rdPath
                        writeFile wrPath x

我得到以下错误:

Couldn't match expected type 'IO t0'
            with actual type 'FilePath -> FilePath -> IO()

但是,当我将"main"的名称更改为其他名称时,文件会正确编译。

main有什么独特之处?为什么它的类型必须是IO t0

因为语言规范是这么说的。

Haskell程序是模块的集合,按照惯例,其中一个模块必须称为Main,并且必须导出值main。程序的值是模块Main中标识符main的值,对于某些类型的t,它必须是类型IO t的计算(见第7章)。当程序被执行时,计算main被执行,并且其结果(类型为t)被丢弃。

正如GolezTrol所说,所有程序都需要知道在调用函数时要开始执行哪个符号。许多脚本语言不需要(或者只是不需要)main例程,因为它们可以将语句放在顶层。Haskell、C和许多其他语言的情况并非如此——这些语言需要一个起始位置,按照惯例,这就是main函数(根据Haskell规范,请参阅Cat的答案)。

请注意,Haskell的main不接受任何与程序参数相对应的参数——这些参数是通过System.Environment.getArgs获得的。

与C、Java或C#一样,main在某些上下文中是一个特殊的标识符,指示程序应该从哪里开始。

在Haskell中,main被定义为具有类型IO a。你应该给你的函数起一个不同的名字,或者如果你真的想让它作为起点,改变它的签名,让它用getArgs 从命令行读取参数

虽然您没有具体询问,但main也很特别,因为它是Haskell程序中唯一可以(安全地)调用IO操作的函数。Haskell运行时将main视为特殊的。

根据定义,main是一个不带参数的函数,它返回由运行时丢弃的IO a类型的值。您的错误消息表明您的main不符合这些要求。确实如此,因为您的main接收到两个参数。

要访问命令行参数,请使用System.Environment.getArgs

Main.main有什么独特之处?

现在Haskell有了一个FFI,它的形象地很简单:

此代码:(有点)最终为:
模块Main(Main)其中
Main::IO()
module Main(),其中
对外出口"Hmain" main::IO()

我知道这个问题很古老,但我想我应该提到,你可以在一个不(显式或隐式)命名为Main的模块中命名任何你想要的main。所以

module Foo where
main :: Int -> Bool
main = (>3)

会编译得很好。但是,如果去掉模块头,或者使用module Main where ...,那么它就不会了。

相关内容

  • 没有找到相关文章

最新更新