Haskell 在这种特殊情况下,为什么接收到的错误变量不在范围内?

Haskell 在这种特殊情况下,为什么接收到的错误变量不在范围内?,haskell,Haskell,当我使用以下代码创建一个.hs文件并使用:l将其加载到ghci时,该文件会加载,但如果我询问符号的类型,我会收到错误:1:1:error:Variable not in scope:symbol。我知道这意味着我使用的名称在我尝试使用它的地方没有定义,但我看不出代码有什么问题: module MyData (MetricUnit(..), ImperialUnit(..), Measurement(..), convert) where data MetricUnit = Meter

当我使用以下代码创建一个.hs文件并使用
:l
将其加载到ghci时,该文件会加载,但如果我询问
符号的类型,我会收到错误
:1:1:error:Variable not in scope:symbol
。我知道这意味着我使用的名称在我尝试使用它的地方没有定义,但我看不出代码有什么问题:

module MyData
(MetricUnit(..),
 ImperialUnit(..),
 Measurement(..),
 convert)
 where

data MetricUnit = Meter | Liter | KiloGram
              deriving (Show, Eq)

data ImperialUnit = Yard
                    | Gallon
                    | Pound
                      deriving (Show, Eq)

data Measurement = MetricMeasurement Double MetricUnit
             | ImperialMeasurement Double ImperialUnit
               deriving (Show)

symbol :: MetricUnit -> String
symbol Meter = "m"
symbol Liter = "L"
symbol KiloGram = "kg"

convert (MetricMeasurement x u)
     | u==Meter    = ImperialMeasurement (1.0936*x) Yard
     | u==Liter    = ImperialMeasurement (0.2642*x) Gallon
     | u==KiloGram = ImperialMeasurement (2.2046*x) Pound

convert (ImperialMeasurement x u)
      | u==Yard   = MetricMeasurement (0.9144*x) Meter
      | u==Gallon = MetricMeasurement (3.7854*x) Liter
      | u==Pound  = MetricMeasurement (0.4536*x) KiloGram

在ghci中键入多行内容时(如类型声明、类定义、
派生另一行的
子句),必须进入多行模式。您可以输入
:{
,这将使您进入多行提示,然后输入您的代码,然后在另一行输入
:}
,退出多行提示。然后,它会将您的代码解释为一个块,而不是许多行。

在ghci中键入多行内容(如类型声明、类定义、
派生另一行的
子句)时,您必须进入多行模式。您可以输入
:{
,这将使您进入多行提示,然后输入您的代码,然后在另一行输入
:}
,退出多行提示。然后,它会将您的代码解释为一个块,而不是许多行。

我将从“无法复制”开始:

%cat数据计量单位=米|升|千克
推导(显示,等式)
符号::公制单位->字符串
symbol Meter=“m”
symbol L=“L”
符号kg=“kg”
heredoc>EOF
tommd@ovdak/tmp%ghci ap.hs
GHCi,8.6.4版:http://www.haskell.org/ghc/  :? 求救
已从/Users/tommd/.ghc/x86_64-darwin-8.6.4/environments/default加载包环境
包标志已更改,正在重置和加载新包。。。
已从/Users/tommd/.GHCi加载GHCi配置
[1/1]编译主要内容(美联社、口译)
好的,加载了一个模块。
*Main>
所以它的负载很好

也许您正试图在GHCi中定义代码,而不是从文件中加载代码?在本例中,请参见@Aplet123关于多行的回答。对于您可能正在使用的GHCi中断使用的示例,请考虑:

*Main> foo :: Bool

<interactive>:1:1: error: Variable not in scope: foo :: Bool
*Main> foo = True
*Main>foo::Bool
:1:1:错误:变量不在范围内:foo::Bool
*Main>foo=True
输入第一行后,GHCi尝试向您显示foo(
print(foo::Bool)
)和nothave
foo
,它将告诉您foo不在范围内。同样,请看另一个答案。

我将从“无法复制”开始:

%cat数据计量单位=米|升|千克
推导(显示,等式)
符号::公制单位->字符串
symbol Meter=“m”
symbol L=“L”
符号kg=“kg”
heredoc>EOF
tommd@ovdak/tmp%ghci ap.hs
GHCi,8.6.4版:http://www.haskell.org/ghc/  :? 求救
已从/Users/tommd/.ghc/x86_64-darwin-8.6.4/environments/default加载包环境
包标志已更改,正在重置和加载新包。。。
已从/Users/tommd/.GHCi加载GHCi配置
[1/1]编译主要内容(美联社、口译)
好的,加载了一个模块。
*Main>
所以它的负载很好

也许您正试图在GHCi中定义代码,而不是从文件中加载代码?在本例中,请参见@Aplet123关于多行的回答。对于您可能正在使用的GHCi中断使用的示例,请考虑:

*Main> foo :: Bool

<interactive>:1:1: error: Variable not in scope: foo :: Bool
*Main> foo = True
*Main>foo::Bool
:1:1:错误:变量不在范围内:foo::Bool
*Main>foo=True

输入第一行后,GHCi尝试向您显示foo(
print(foo::Bool)
)和nothave
foo
,它将告诉您foo不在范围内。同样,请参见另一个答案。

我想问题在于您的模块是以这种方式启动的:

module MyData
    (MetricUnit(..),
     ImperialUnit(..),
     Measurement(..),
     convert)
where
因此,模块不会导出函数
符号

在GHCi中,从命令行将模块加载为
GHCi MyData.hs
,或从GHCi提示符加载为
:load MyData
,应绕过导出列表,并允许您访问所有内容

您还可以将
符号
添加到导出列表中


您得到这个错误是因为(我猜)您使用的是另一种方法来导入模块,它不会让您访问未导出的标识符。也许您正在通过另一个模块导入该模块?

我想问题在于您的模块以这种方式启动:

module MyData
    (MetricUnit(..),
     ImperialUnit(..),
     Measurement(..),
     convert)
where
因此,模块不会导出函数
符号

在GHCi中,从命令行将模块加载为
GHCi MyData.hs
,或从GHCi提示符加载为
:load MyData
,应绕过导出列表,并允许您访问所有内容

您还可以将
符号
添加到导出列表中


您得到这个错误是因为(我猜)您使用的是另一种方法来导入模块,它不会让您访问未导出的标识符。可能是通过另一个模块导入该模块?

问题是由于存在另一个同名文件


当我用新文件名创建一个新文件时,问题得到了解决。

问题是由于存在另一个同名文件


当我用新文件名创建新文件时,问题得到了解决。

否,我没有在GHCI中定义它。我正在使用一个文件。推导是在另一行。代码来自这里。它会加载,但当我询问符号类型时,我收到范围错误。@Edward.Lin您的代码看起来很好。您是否成功地将其加载到GHCi中?例如,你能成功地评估
Meter
吗?@Chi是的,我成功了。仪表评估成功。不,我没有在GHCI中定义它。我正在使用一个文件。推导是在另一行。代码来自这里。它会加载,但当我询问符号类型时,我收到范围错误。@Edward.Lin您的代码看起来很好。您是否成功地将其加载到GHCi中?例如,你能成功地评估
Meter
吗?@Chi是的,我成功了。和仪表成功计算。要将
符号添加到