【发布时间】:2020-05-04 17:06:49
【问题描述】:
我正在用 Haskell 编写一种简单的语言,但在计算算术和关系表达式时遇到了问题。起初我写了一个评估函数,然后我意识到我需要单独的函数来评估我语言的各个方面。所以我有一个算术评估函数,一个关系评估函数,然后是一个通用评估函数。
这个问题源于实际产生了一些可以使用的东西,我认为这是因为无法将我的其他 eval 函数与我的主要 eval 函数相关联。但是我不确定我是否错误地接近评估。我相信,也许像“foldl1”这样的功能在评估中会更有用。我第一次从 48 小时内编写自己的方案 Wikibook 中了解到这个函数,它似乎比评估每个可能的表达式更有用。我不确定这将如何在我当前的代码中实现,除非我对每个表达式都有一个函数。例如,如果我有一个像“1 + 1”这样的表达式,我当前的解析器会将其解析为“1 Add 1”,但如果我使用 foldl1,我可以有一个函数来获取这个表达式的每个部分并“折叠”运算符上的参数。即使我将我当前的评估函数与 foldl1 的想法合并,我仍然预见到在评估任何有意义的东西时会出现问题,而不仅仅是整数或字符串。
任何方向或帮助将不胜感激。
下面我已经包含了数据类型和我的评估函数:
data HenryVal = Atom String
| String String
| Integer Integer
| Bool Bool
| Not HenryVal
| Neg HenryVal
| List [HenryVal]
| Seq [HenryVal]
| Assign String HenryVal
| If HenryVal HenryVal HenryVal
| While HenryVal HenryVal
| Skip
| ABinary ABinOp HenryVal HenryVal
| BBinary BBinOp HenryVal HenryVal
| RBinary RBinOp HenryVal HenryVal
data BBinOp = And | Or deriving (Show)
data RBinOp = Greater | Less deriving (Show)
data ABinOp = Add
| Subtract
| Multiply
| Divide
deriving (Show)
evalABinOP :: HenryVal -> ABinOp -> HenryVal -> HenryVal
evalABinOP (Integer a) Add (Integer b) = Integer (a + b)
evalABinOP (Integer a) Multiply (Integer b) = Integer (a * b)
evalABinOP (Integer a) Divide (Integer b) = Integer (a `div` b)
evalABinOP (Integer a) Subtract (Integer b) = Integer (a - b)
evalRBinOp :: HenryVal -> RBinOp -> HenryVal -> HenryVal
evalRBinOp (Integer a) Greater (Integer b) = if a > b then (Bool True) else (Bool False)
evalRBinOp (Integer a) Less (Integer b) = if a < b then (Bool True) else (Bool False)
evalStmt :: HenryVal -> [HenryVal]
evalStmt (Assign var val) = [val]
evalCond :: HenryVal -> Bool
evalCond (Bool cond) = if cond == True then True else False
eval :: HenryVal -> HenryVal
eval val@(Atom _) = val
eval val@(String _) = val
eval val@(Integer _) = val
eval val@(Bool _) = val
eval val@(Neg _) = val
eval val@(Not _) = val
eval (List [Atom "quote", val]) = val
eval val@(List _) = val
eval val@(Seq _) = val
eval (If cond a b) = if (evalCond cond) then (eval a) else (eval b)
eval (Assign var val) = eval val
eval (Seq (Atom func : args)) = apply func $ map eval args
eval (ABinary op x y) = evalABinOP x op y
eval (RBinary op x y) = evalRBinOp x op y
错误信息:
./hask "[4 + 4]"
"No match: "Henry" (line 1, column 4):
unexpected "+"
expecting space, "(", "if", ";Do", "skip", identifier, letter, digit, "\"" or "[""
在 48 小时内为自己编写一个方案:https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours/Evaluation,_Part_1
【问题讨论】:
-
在我看来你做得很好。您已经成功地将您的专业评估功能与您的主要评估功能相关联。你在寻求什么帮助?我看不到 foldl1 可以神奇地解决您的问题的任何方式-也许像 catamorphism 这样的更一般的概念可能会有所帮助,但这似乎有点棘手,因为您的 List 构造函数需要特殊情况,而 cata 的意义在于它确实为你所有的递归。
-
我想我不明白的是因为没有更好的术语而让它发挥作用。我不确定如何将任意表达式与评估函数相关联并获得我想要的结果。例如,我可以声明一个数字,但说对数字进行平方会使我得到一个错误,说操作员是意外的。
-
包括导致错误的确切输入以及错误本身,以便我们重现您的问题。
-
您发布的错误消息是由解析器生成的,而不是您的评估函数。因此,您的解析器代码中有一些内容不希望在此位置出现
+符号。 -
您添加了错误,但绝对不是产生它的代码。这非常需要minimal reproducible example——就目前而言,这是无法回答的。
标签: parsing haskell functional-programming evaluation