使用此代码:
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
)被丢弃。
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 ...
,那么它就不会了。