我正在学习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,这对我来说很困惑。一些帮助将不胜感激。
答案 0 :(得分:1)
让我们看一下错误:
Variable not in scope: evaluate :: t0 -> Integer -> t Data constructor not in scope: Constant
这意味着您尚未定义evaluate
函数和Constant
构造函数(即使您显然已经定义了)。但是您说当您使用getValue
和X
时,这些有效吗?
这似乎不是(极端常见的)多行ghci
的混淆,如注释中所建议。首先,您从中得到的错误通常是non-exhaustive patterns
,这不是您得到的错误。其次,您的ghci
提示符将读取*Main>
而不是Prelude>
,这意味着您已:load
编辑了一个文件。该文件只是没有定义您期望的代码。
我的猜测是,您在文件中编写了代码的第一部分,然后正确地:load
对其进行了编辑,然后修改了文件并忘记了:reload
,因此从未进行过更改加载。
另一种可能性是,您在文件的开头放置了module Main (VariableName (..), getValue) where
,却忘记了向其中添加新的导出内容。但这似乎不太可能。
如果以上方法均无效,请尝试关闭ghci
,再次将其打开,然后:load
重新创建文件。
即使您解决了该问题,也会遇到许多其他错误,大部分与括号有关。在Haskell中,当您编写如下内容时:
evaluate Constant 20
这意味着“调用evaluate
函数,并向它传递两个参数:Constant
和20
”。这意味着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
这些模式中的每一个都期望使用不同数量的参数:前两个期望使用两个参数,后两个期望使用三个参数。问题在于x
和y
被视为函数的参数,而不是构造函数。要更改此设置,您需要括号:
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
这些构造函数中目前没有一个接受参数:它们是值(例如True
,X
,Nothing
等),而不是值构造函数。这不是您想要的。您需要为每个构造函数指定参数的类型,如下所示:
data Expression = Constant Int
| Variable VariableName
| Add Int Int
| Multiply Int Int
deriving Show