Haskell 将.hs脚本加载到解释器中

Haskell 将.hs脚本加载到解释器中,haskell,ghci,Haskell,Ghci,在Haskell ghci,我试过 Prelude> :load filename.hs Ok, modules loaded: Main. 很遗憾,我无法运行文件中定义的任何函数。我编译该文件时没有任何错误,但调用函数时会出现错误,“notin scope:(function name)”。奇怪的是,不久前我在运行这个程序时没有遇到任何问题…很难准确猜出问题出在哪里。您是否将文件顶部的行更改为: module Main where module Main (main) where

在Haskell ghci,我试过

Prelude> :load filename.hs
Ok, modules loaded: Main.

很遗憾,我无法运行文件中定义的任何函数。我编译该文件时没有任何错误,但调用函数时会出现错误,“notin scope:(function name)”。奇怪的是,不久前我在运行这个程序时没有遇到任何问题…

很难准确猜出问题出在哪里。您是否将文件顶部的行更改为:

module Main where
module Main (main) where
例如:

module Main where
module Main (main) where

如果您这样做了,它将只导出
main
函数。

很难准确猜测问题出在哪里。您是否将文件顶部的行更改为:

module Main where
module Main (main) where
例如:

module Main where
module Main (main) where

如果您这样做了,它将只导出
main
函数。

问题是您的编辑器正在使用类似

$ ghc foo.hs
由于您的文件没有模块声明,GHC假定该模块名为
Main
,因为您没有另行指定,并且由于它正在编译完整的程序,因此不会导出除
Main
之外的任何定义;也就是说,它的作用就像您有一个模块声明,如:

module Main (main) where
鉴于GHCi默认为:

module Main where
它们指定要编译的模块的名称以及导出的值。对于第一个声明,仅从模块导出
main
;对于第二种情况,将导出每个顶级值。无法从模块外部访问未导出的值,这就是GHCi中出现“不在范围内”错误的原因


GHCi的不一致行为可能是为了使测试代码更容易;加载文件并使用其定义不需要模块声明。解决方案是将
模块Main(或其他模块名)放在文件的顶部,这样可以显式导出所有内容。就我个人而言,我认为这种行为令人困惑,GHC和GHCi的行为可能应该更改为一致。

问题在于,您的编辑器在编译代码时使用了类似于

$ ghc foo.hs
由于您的文件没有模块声明,GHC假定该模块名为
Main
,因为您没有另行指定,并且由于它正在编译完整的程序,因此不会导出除
Main
之外的任何定义;也就是说,它的作用就像您有一个模块声明,如:

module Main (main) where
鉴于GHCi默认为:

module Main where
它们指定要编译的模块的名称以及导出的值。对于第一个声明,仅从模块导出
main
;对于第二种情况,将导出每个顶级值。无法从模块外部访问未导出的值,这就是GHCi中出现“不在范围内”错误的原因


GHCi的不一致行为可能是为了使测试代码更容易;加载文件并使用其定义不需要模块声明。解决方案是将
模块Main(或其他模块名)放在文件的顶部,这样可以显式导出所有内容。就我个人而言,我认为这种行为令人困惑,GHC和GHCi的行为可能应该改变为一致。

语言标准规定,如果没有给出模块声明,则默认为
模块主(Main),其中
。当编译Haskell源文件并将其加载到ghci中时,只有相关模块的导出实体在范围内。在您的情况下,没有模块声明,这只是
main
函数

但是,由于这在开发时非常不方便,ghci可以加载范围更广的解释模块,参见。以该形式加载的模块在提示符中的模块名称前用星号表示,对于此类模块,不仅模块中定义的每个顶级实体都在作用域中,而且导入的实体也在作用域中,当以该形式加载模块时,ghci提示符中也会显示模块顶级作用域中的所有内容

这允许在开发中方便地测试函数,因此是一件好事™. 另一方面,@ehird正确地提到,行为上的差异可能令人困惑,因此是一件坏事


总的来说,我认为ghci在
*模块
s范围更广的优势大于不一致性。

语言标准规定,如果没有给出模块声明,则隐式地
模块主(Main),其中
。当编译Haskell源文件并将其加载到ghci中时,只有相关模块的导出实体在范围内。在您的情况下,没有模块声明,这只是
main
函数

但是,由于这在开发时非常不方便,ghci可以加载范围更广的解释模块,参见。以该形式加载的模块在提示符中的模块名称前用星号表示,对于此类模块,不仅模块中定义的每个顶级实体都在作用域中,而且导入的实体也在作用域中,当以该形式加载模块时,ghci提示符中也会显示模块顶级作用域中的所有内容

这允许在开发中方便地测试函数,因此是一件好事™. 另一方面,@ehird正确地提到,行为上的差异可能令人困惑,因此是一件坏事


总的来说,我认为ghci在
*模块
s范围更广的优势大于不一致性。

您以前可能编译过该模块,因此目录中有
.o
.hi
文件。当GHCi找到这些时,默认情况下它将以编译模式加载模块,这意味着只有从模块导出的内容在范围内

如果未包含模块声明,则默认情况下仅为
main
,因为默认模块声明为
module main(main),其中
。这也是