在Haskell文件中使用main函数

4
我已经在GHCI中使用过Haskell编程了,但我们下一个作业需要我们只使用GHC来编译和测试我们的代码。
由于ghci与ghc的工作方式不同,你需要使用一个 main 函数,并且ghc会在你的代码中寻找这个函数。
我的问题是,如果Haskell提倡类型安全和除了IO操作之外没有副作用,为什么任何Haskell程序的主要部分都必须是一个IO操作?
如果我理解有误,请原谅,我只是找不到任何最终解释这个问题的资源。

3
Simon Peyton-Jones 关于 IO 的说法是:"I/O 是每个程序存在的原因。如果一个程序没有任何可观察的效果(没有输入,没有输出),那么它就不会很有用。" - chi
请注意,每当您在 GHCi 中执行类似 3<Enter> 的操作时,实际上您正在编写并运行程序 main = print 3 - Luc Danton
1
请注意,尽管这个问题非常简单,但它属于那种非常简单,以至于没有人在任何地方解释过它。 - MathematicalOrchid
3个回答

13
如果你的main函数不是一个IO操作,那么它只能产生一个结果。由于Haskell是惰性的,这(通常)意味着它仅仅生成一个承诺,即将要执行计算,但直到需要使用时才会计算它。由于确保某个东西被计算的通常方法是打印该值,或将其发送到网络,保存到磁盘或将其用于某种其他类型的IO,因此你的结果不会被计算,程序将简单地退出。想象一个虚假的程序,像是:
main :: Int
main = 1 + 1

假设你可以编译并运行这段代码,你期望会发生什么?没有任何内容被打印出来,也没有要求得到 main 的结果,Haskell 只是创建了一个承诺,在某个时刻计算 1 + 1 ,然后退出程序。基本上,在顶层没有 IO 的情况下你不能做任何有趣的事情,而因为我们希望程序可以做有趣的事情,所以我们需要让顶层成为一个 IO 操作。


这很棒。解释得非常清楚!现在我要尝试摆脱所有的类型匹配错误,让我的结果进入 IO () ;) - Bradley
@Bradley 如果你的程序只是计算一些东西然后打印出答案,那么你的 main 理想情况下应该是这样的 main = print answer,其中 answer = <some expression>。如果你提前知道所有的输入,那么你可以在 answer 中提供它们。如果你需要使用命令行参数或从文件中读取,你应该编写你的代码,使得所有的工作都是通过纯函数完成的,然后你的主函数可能是 main = do { filecontents <- readFile "somefile.txt"; print $ doSomethingWithFileContents filecontents } - bheklilr
我创建了一个类型,只是想让我的主函数打印出这个类型本身,因为我正在派生show,只是为了在没有ghci的情况下使用haskell。我不知道如何将我的类型转换为IO操作! - Bradley
调用print myTemp时,我收到了“.: createDirectory: invalid argument (Invalid argument)”的错误提示,我快要放弃了!哈哈哈 - Bradley
2
@Bradley 我建议你提出一个单独的问题,附上你遇到困难的具体代码,没有上下文我不知道那个错误是什么意思。 - bheklilr
显示剩余2条评论

4
简单来说,运行程序是一种副作用。这就是为什么顶级函数是一个I/O操作的原因。
理想的Haskell程序是由大量纯代码和薄薄的I/O“外壳”组成的。

2

我认为这很简单 - 最终,你需要每个程序在顶层进行IO操作 - 否则你怎么知道它是否做了任何事情,或者 - 它有多有用呢?所以你必须要有控制台I/O、网络I/O、磁盘I/O或类似的东西。我不明白你怎么能避免这些。


程序具有退出状态,可以视为没有副作用的输出。我的意思是,在C语言中,main函数接受一个字符串列表并返回一个整数。程序可以处理参数并返回一个没有副作用的整数(仍然有用)。 - mb14
假设你能够在不进行IO的情况下获取到命令行参数... 你可以吗? - blazej
正如你所说,“你需要每个程序在顶层进行IO”,但这不一定是在普通的 Haskell 中。我的意思是,归根结底,“IO()”并不执行任何IO操作(甚至什么都不做),直到某种神明采取这个动作并决定执行它。这个神明是你的Haskell程序和系统之间的层。执行main :: IO()只是一个约定,人们可以想象这个神明可以使用命令行参数调用纯净的main :: [String] -> Int并返回其结果。最终的程序将使用IO,但不是Haskell部分。 - mb14

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