我正在努力完成我们给予的任务。我在这里根据不同的指南略微编写了这段代码:Not in scope: data constructor
我遇到的问题是这里的管道:
| x == "+" = (Sum y y',xs'') where
问题似乎与3个管道或管道跟在“哪里”有关。如果我交换最后2个管道。 放
x == "+" = (Sum y y' (...))
之前
x == "*" = (Prod y y' (...))
导致错误移动到该代码。如果我注释掉这两个代码段中的任何一个,一切正常,但我需要它们来完成我们给出的赋值。
快速摘要:
| x == "*" = (Prod y y',xs'') where
(y,xs') = ast xs
(y',xs'') = ast xs'
和
| x == "+" = (Sum y y',xs'') where
(y,xs') = ast xs
(y',xs'') = ast xs'
两者都单独工作,但当我把它们放在一起时,我的程序无法编译。
完整代码:
import Data.Char
data AST = Leaf Int
| Sum AST AST
| Min AST
| Prod AST AST
deriving Show
tokenize::String -> [String]
tokenize[] = []
tokenize('+':xs) = "+": tokenize xs
tokenize('-':xs) = "-": tokenize xs
tokenize('*':xs) = "*": tokenize xs
tokenize(x:xs) = if isDigit x then (takeWhile isDigit (x:xs)) : tokenize (dropWhile isDigit xs) else tokenize(xs)
ast :: [String] -> (AST,[String])
ast [] = error "Empty string"
ast (x:xs) | all isDigit x = (Leaf (read x),xs)
| x == "-" = let (y,xs') = ast xs in (Min y,xs')
| x == "*" = (Prod y y',xs'') where
(y,xs') = ast xs
(y',xs'') = ast xs'
| x == "+" = (Sum y y',xs'') where
(y,xs') = ast xs
(y',xs'') = ast xs'
答案 0 :(得分:7)
中的问题
ast [] = error "Empty string"
ast (x:xs) | all isDigit x = (Leaf (read x),xs)
| x == "-" = let (y,xs') = ast xs in (Min y,xs')
| x == "*" = (Prod y y',xs'') where
(y,xs') = ast xs
(y',xs'') = ast xs'
| x == "+" = (Sum y y',xs'') where
(y,xs') = ast xs
(y',xs'') = ast xs'
是函数定义中每个方程只能有一个where
子句。因此,在where
替代中的x == "*"
之后,解析器期望模式(x:xs)
的等式完成。
只需删除有问题的where
,where
子句的范围是等式中的所有备选方案,并且两个where
子句具有相同的内容(并且缩进更好,{根据我的偏好,{1}}属于自己的行。由于第一个备选方案中的where
使用了let
子句中也存在的绑定,因此也可以删除:
where
答案 1 :(得分:1)
这样做的一种方法是使用let
代替where
:
ast :: [String] -> (AST,[String])
ast [] = error "Empty string"
ast (x:xs) | all isDigit x = (Leaf (read x),xs)
| x == "-" = let (y,xs') = ast xs in (Min y,xs')
| x == "*" = let
(y,xs') = ast xs
(y',xs'') = ast xs'
in (Prod y y',xs'')
| x == "+" = let
(y,xs') = ast xs
(y',xs'') = ast xs'
in (Sum y y',xs'')
您可以在let
内拥有任意数量的定义,而不只是一个。
where
语句在最后范围内,而let
语句在in
结束。这就是您收到错误消息的原因 - 它认为您仍然在where
,但您想要继续。将您的where
条款推迟到最后。
在这种情况下,您并不需要将它们分开,因此可以将它们合并到一个地方,但let
通常对此问题很有用。