Haskell 数据构造函数不在范围内

Haskell 数据构造函数不在范围内,haskell,functional-programming,Haskell,Functional Programming,我正在学习Haskell并编写一个简单的程序。现在我遇到了一个问题,对我来说,这是相当令人困惑的。代码如下: data VariableName = X|Y deriving Show getValue :: VariableName -> Int getValue X = 5 getValue Y = 13 data Expression = Constant|Variable|Add|Multiply deriving Show evaluate :: Expression -&

我正在学习Haskell并编写一个简单的程序。现在我遇到了一个问题,对我来说,这是相当令人困惑的。代码如下:

data VariableName = X|Y deriving Show  
getValue :: VariableName -> Int
getValue X = 5
getValue Y = 13

data Expression = Constant|Variable|Add|Multiply deriving Show
evaluate :: Expression -> Int
evaluate Constant x = x
evaluate Variable x = getValue x
evaluate Add x y = x+y
evaluate Multiply x y = x * y
我预计产出:

Constant  20  = 20
但是我越来越

*Main> evaluate Constant 20

<interactive>:79:1: error:
    Variable not in scope: evaluate :: t0 -> Integer -> t

<interactive>:79:10: error: Data constructor not in scope: Constant

这是正确的答案。我刚开始学习Haskell,这对我来说是相当混乱的。非常感谢您的帮助。

让我们看看错误:

这意味着您尚未定义
evaluate
函数和
常量
构造函数(尽管您显然已经定义了)。但是你说,当你使用
getValue
X
时,这些都有效吗

这似乎不像评论中所说的那样(非常常见)多行
ghci
混乱。首先,您从中得到的错误往往是
非穷举模式
,这不是您得到的。其次,您的
ghci
提示符显示的是
*Main>
,而不是
Prelude>
,这意味着您已经
:加载了一个文件。所述文件根本没有定义您期望它具有的代码

我的猜测是,您在文件中编写了代码的第一部分,然后正确地加载了它,然后修改了文件并忘记了加载,因此您所做的更改从未加载

另一种可能是,您将
模块Main(VariableName(..),getValue)放在文件开头的
位置,而忘记将新导出添加到其中。但这似乎不太可能

如果以上操作都不起作用,只需尝试关闭
ghci
,再次打开它,然后
:重新加载文件


即使解决了这个问题,您也会遇到许多其他错误,主要与括号有关。在Haskell中,当你写这样的东西时:

evaluate Constant 20
它的意思是“调用
求值
函数,并向其传递两个参数:
常量
20
”。这意味着
evaluate::Expression->Int->Int
,但您确实需要
evaluate::Expression->Int
。所以你需要括号:

evaluate (Constant 20)
evaluate :: Expression -> Int
evaluate (Constant x) = x
evaluate (Variable x) = getValue x
evaluate (Add x y) = x+y
evaluate (Multiply x y) = x * y
这意味着“使用一个参数调用
常量
构造函数
20
,并将该值作为单个参数传递给
evaluate


您不仅必须在呼叫站点进行此更改,还需要在定义中进行此更改。目前,您有:

evaluate :: Expression -> Int
evaluate Constant x = x
evaluate Variable x = getValue x
evaluate Add x y = x+y
evaluate Multiply x y = x * y
每个模式都需要不同数量的参数:前两个需要两个参数,后两个需要三个参数。问题是
x
y
被视为函数的参数,而不是构造函数。要更改此设置,需要使用括号:

evaluate (Constant 20)
evaluate :: Expression -> Int
evaluate (Constant x) = x
evaluate (Variable x) = getValue x
evaluate (Add x y) = x+y
evaluate (Multiply x y) = x * y

您需要做的最后一个更改是在构造函数定义中:您需要告诉构造函数他们首先接受参数。当前,您的数据定义如下所示(我添加了格式):

这些构造函数目前都不接受参数:它们是值(比如
True
X
Nothing
,等等),而不是值构造函数。这不是你想要的。您需要给出每个构造函数的参数类型,如下所示:

data Expression = Constant Int
                | Variable VariableName
                | Add      Int Int
                | Multiply Int Int
                deriving Show

您需要添加括号,现在看起来您使用两个变量定义了
计算常数x
。此外,像
常量|变量|添加|乘法
这样的
表达式在一开始似乎没有多大意义,例如,我希望
常量Int |变量VariableName | Add Expression Expression | Multiply Expression
,因为这些是表达式的参数。我猜您是通过ghci逐行输入此代码的,因为代码
evaluate::Expression->Int;evaluate常量x=x
甚至不应与Willem的注释一起编译。@WillemVanOnsem我尝试添加所有可能的偏执论组合,但仍然会出现相同的错误:/
data Expression = Constant Int
                | Variable VariableName
                | Add      Int Int
                | Multiply Int Int
                deriving Show