简体   繁体   English

Haskell中的算术表达式评估

[英]Arithmetic expression evaluation in Haskell

Here i am trying to evaluate the expression in Haskell using defined values of Exp data type. 在这里,我试图使用Exp数据类型的定义值来评估Haskell中的表达式。 The function type would be eval :: Exp -> Int and data type is this: 函数类型是eval :: Exp -> Int ,数据类型是这样的:

data Exp = Num Int
       | Exp :+: Exp
       | Exp :-: Exp
       | Exp :*: Exp
       | Exp :/: Exp
       deriving (Show)

and values which i am trying to evaluate are these: 和我想要评估的价值是这些:

 4 + 5 * 6 , respecting correct precedences of the operators
 4 + 5 + 6 , respecting, that + binds left-associative
 (4 + 3) * (5 - 2)
 4 + (4 / (2 - 2))

So far this logic is working fine which is: 到目前为止,这个逻辑工作得很好,这是:

eval :: Exp -> Int
eval (Num a) = a 
eval (a :+: b) = (eval a) + (eval b)
eval (a :-: b) = (eval a) - (eval b)
eval (a :*: b) = (eval a) * (eval b)
eval (a :/: b) = (eval a) `div` (eval b)

When i pass this i get 3 as output which is correct: 当我通过这个我得到3作为输出是正确的:

eval (Num 2 :+: Num 2 :-: Num 1) 
output = 3 

but i am confused how it evaluated the second part of the expression which :-: what i understood the only pattern matched in first iteration was eval (a :+: b) = (eval a) + (eval b) which returned 4 as output how it carries 4 to next iteration to perform the :-: operation? 但我很困惑它如何评估表达式的第二部分:-:我理解在第一次迭代中匹配的唯一模式是eval (a :+: b) = (eval a) + (eval b) ,返回4为输出它如何进行4到下一次迭代来执行:-: operation?

before that i was trying something like this: 在此之前,我尝试这样的事情:

eval :: Exp -> Int
eval (Num a) = a
eval (Num a :+: Num b) = eval (Num a) + eval (Num b)
eval (Num a :-: Num b) = eval (Num a) - eval (Num b)
eval (Num a :*: Num b) = eval (Num a) * eval (Num b)
eval (Num a :/: Num b) = eval (Num a) `div` eval (Num b)

it didn't give the desired results and then i just changed it to the first version. 它没有给出预期的结果然后我只是将它改为第一个版本。 it worked fine but didn't get the proper semantics of it. 它工作正常,但没有得到它的正确语义。 Any help? 有帮助吗? Please don't hesitate to go into details. 请不要犹豫,详细了解。 Thanks in advance. 提前致谢。

The default fixity for operators is infixl 9 (see 4.4.2 Fixity Declarations ). 运算符的默认固定性是infixl 9 (参见4.4.2 Fixity Declarations )。

You have not declared the fixity for your :+: etc. operators. 您尚未为您的:+:等运营商声明固定性。

This means that your expression gets parsed as 这意味着您的表达式被解析为

eval ((Num 2 :+: Num 2) :-: Num 1)  :: Exp

--     Num 2                        :: Exp 
--               Num 2              :: Exp 
--     Num 2 :+: Num 2              :: Exp 
--                          Num 1   :: Exp 
--    (Num 2 :+: Num 2) :-: Num 1   :: Exp 

So the evaluation proceeded as 所以评估继续进行

  eval ((Num 2 :+: Num 2) :-: Num 1)  -- match with:
  eval (a                 :-: b    ) = (eval a) - (eval b)
                                     =  ....

As pointed out in other answers, the problem is that all your constructors have the same default precedence: they are left-associative with high (9) precedence. 正如在其他答案中指出的那样,问题是所有构造函数都具有相同的默认优先级:它们是左关联的,具有高(9)优先级。 You can change that using the infixl directive. 您可以使用infixl指令更改它。

data Exp = Num Int
       | Exp :+: Exp
       | Exp :-: Exp
       | Exp :*: Exp
       | Exp :/: Exp
       deriving (Show)

-- Using the same precedences as (+), (-), (*), and (/)
infixl 6 :+:, :-:
infixl 7 :*:, :/:

Now eval $ Num 4 :+: Num 2 :*: Num 3 will correctly return 10 instead of 18. 现在eval $ Num 4 :+: Num 2 :*: Num 3将正确返回10而不是18。

I think the easiest way to follow what's going on here is just to follow the evaluation through one step at a time. 我认为遵循这里发生的事情最简单的方法就是一步一步地完成评估。 Since as @WillNess has explained the default order of operation is from left to right, your code is evaluated as follows (each individual step comes directly from one of the lines of your definitioni of eval ): 由于@WillNess已经解释了默认的操作顺序是从左到右,因此您的代码将按如下方式进行评估(每个步骤直接来自您的eval定义的一行):

eval ((Num 2 :+: Num 2) :-: Num 1)
eval (Num 2 :+: Num 2) - eval(Num 1)
(eval (Num 2 :+: Num 2)) - 1
(eval (Num 2) + eval (Num 2)) - 1
(2 + 2) - 1
4 - 1
3

I hope this makes it clear. 我希望这说清楚。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM