数据构造函数不在范围内

时间:2019-01-19 18:32:45

标签: 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 -> 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

但是例如:我写

*Main> getValue X
5

哪个是正确的答案。我刚刚启动Haskell,这对我来说很困惑。一些帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

让我们看一下错误:

Variable not in scope: evaluate :: t0 -> Integer -> t

Data constructor not in scope: Constant

这意味着您尚未定义evaluate函数和Constant构造函数(即使您显然已经定义了)。但是您说当您使用getValueX时,这些有效吗?

这似乎不是(极端常见的)多行ghci的混淆,如注释中所建议。首先,您从中得到的错误通常是non-exhaustive patterns,这不是您得到的错误。其次,您的ghci提示符将读取*Main>而不是Prelude>,这意味着您已:load编辑了一个文件。该文件只是没有定义您期望的代码。

我的猜测是,您在文件中编写了代码的第一部分,然后正确地:load对其进行了编辑,然后修改了文件并忘记了:reload,因此从未进行过更改加载。

另一种可能性是,您在文件的开头放置了module Main (VariableName (..), getValue) where,却忘记了向其中添加新的导出内容。但这似乎不太可能。

如果以上方法均无效,请尝试关闭ghci,再次将其打开,然后:load重新创建文件。


即使您解决了该问题,也会遇到许多其他错误,大部分与括号有关。在Haskell中,当您编写如下内容时:

evaluate Constant 20

这意味着“调用evaluate函数,并向它传递两个参数:Constant20”。这意味着evaluate :: Expression -> Int -> Int,但您确实想要evaluate :: Expression -> Int。所以需要括号:

evaluate (Constant 20)

这意味着“用一个参数Constant调用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

这些模式中的每一个都期望使用不同数量的参数:前两个期望使用两个参数,后两个期望使用三个参数。问题在于xy被视为函数的参数,而不是构造函数。要更改此设置,您需要括号:

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

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

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

这些构造函数中目前没有一个接受参数:它们是值(例如TrueXNothing等),而不是值构造函数。这不是您想要的。您需要为每个构造函数指定参数的类型,如下所示:

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