为什么我的Haskell代码说'变量不在范围内:main'?

bra*_*970 10 haskell compiler-errors

当我在repl.it网站上的Haskell的交互式shell中键入以下内容时,它完美地运行.

let squareMe x = x * x
let myFruit = ["banana", "apple", "kiwi", "orange"]
Run Code Online (Sandbox Code Playgroud)

但是,当我将其键入源文件并单击"运行"时,我收到错误:

<interactive>:3:1: error:
    • Variable not in scope: main
    • Perhaps you meant ‘min’ (imported from Prelude)
Run Code Online (Sandbox Code Playgroud)

我一直在努力理解这个错误,并提出了几个小时的解决方案,并且不再寻找解决方案或理解错误意味着什么.

AJF*_*mar 15

Haskell REPL(GHCi)和实际的Haskell程序有很大不同.

造成这种差异的原因是两种格式的目标.首先,GHCi是一个测试区域,而不是代码运行区域.但是,Haskell源文件旨在运行某个名为的进程main.当您运行源文件时,Haskell编译器(通常是GHC)会查找IO被调用的操作main,并尝试运行它.在这种情况下,没有main,所以它失败了.

其次,你输入的内容不是有效的Haskell程序,那些声明在GHCi中会很好,但在Haskell源中则不行.这在源文件中是正确的:

squareMe x = x * x

myFruit = ["banana", "apple", "kiwi", "orange"]
Run Code Online (Sandbox Code Playgroud)

注意缺乏let; Haskell源文件不使用它来声明事物.

请注意,在repl.it,这仍然会抱怨说main丢失了,但你可以参考squareMemyFruit在REPL无后顾之忧.换句话说,错误仍然会出现,但无关紧要,因为你可以使用你在文件中写的任何内容.

如果要禁止警告,可以编写以下行:

main :: IO ()    -- This says that main is an IO action.
main = return () -- This tells main to do nothing.
Run Code Online (Sandbox Code Playgroud)

你可以用程序做很多事情而不是这个.以下是几个例子:

  • main = putStrLn "No errors!"No errors!在您运行时打印.
  • main = print myFruit["banana", "apple", "kiwi", "orange"]在您运行时打印.

请注意,这个答案主要适用于网站repl.it,但一般来说这是Haskell程序的结构.


msc*_*idt 8

如果您编译 Haskell 源代码,则需要一个main符号作为入口点,就像编译 C 程序时一样。同样在编译文件中,您必须跳过lets。例如

squareMe x = x * x

main = putStrLn . show $ squareMe 4
Run Code Online (Sandbox Code Playgroud)

  • `print x = putStrLn (show x)`,所以你的代码调用了两次 `show`。 (2认同)