Haskell,用于求解基本方程的函数

时间:2015-03-22 05:28:20

标签: list haskell math recursion pattern-matching

我是haskell的新手并且已经开始了因为我在UNI做了这件事, 我以前有过C,C#和HTML,CSS的经验。我们有一个实验室 我们获得代码的那一周:

data Token = Plus | Minus | Times | Divided_By | Power | Num {number :: Double}
deriving (Show, Eq)

type Expression = [Token]

tokenizer :: String -> Expression
tokenizer expression_as_string = case expression_as_string of
   ""    -> []
   c: cs -> case c of
      '+' -> Plus        : tokenizer cs
      '-' -> Minus       : tokenizer cs
      '*' -> Times       : tokenizer cs
      '/' -> Divided_By  : tokenizer cs
      '^' -> Power       : tokenizer cs
      _ | c `elem` ['0' .. '9'] -> case reads expression_as_string of
                                      [(value, rest)] -> Num value : tokenizer rest
                                      _               -> error "Could not read number"
        | c `elem` [' ', '\t'] -> tokenizer cs
        | otherwise -> error "Unknown Symbol"

expression_to_string :: Expression -> String
expression_to_string expr = case expr of
   []    -> ""
   e: es -> case e of
      Plus       -> " + "     ++ expression_to_string es
      Minus      -> " - "     ++ expression_to_string es
      Times      -> " * "     ++ expression_to_string es
      Divided_By -> " / "     ++ expression_to_string es
      Power      -> " ^ "     ++ expression_to_string es
      Num x      -> (show x)  ++ expression_to_string es

eval_string_expression :: String -> String
eval_string_expression s = expression_to_string (eval (tokenizer s))

所以现在我们打算实现一个名为eval的自己的函数,它应该在ghci中输入时解决这个等式:

  

eval [Num 3.2,Plus,Minus,Num 4.2,Minus,Num 5.3,Plus,Num 6.3]       [Num {number = 0.0}]

所以在这一点上我已经使用了模式匹配(判断我理解它)并且做到了这一点:

eval :: Expression -> Expression
eval list = case list of
   [] -> []
   [Num x, op, Num y] -> case op of
      Plus           -> [Num (x + y)]
      Minus         -> [Num (x - y)]
      Times         -> [Num (x * y)]
      Divided_By -> [Num (x / y)]
      Power         -> [Num (x ** y)]
      _                -> error "......"

现在如果我输入ghci:eval [Num 3.1,Plus,Num 4.2] 它返回7.300000000001,因为它是一个双,现在我不确定这是否正确。 虽然我知道这不是详尽无遗的,因为我没有照顾所有的可能性。 我需要帮助的是考虑负数,例如Minus,Plus应该返回减号,但我还需要注意顺序如何工作,例如Powers,然后乘法/除法然后加法/减法。 如果调用eval函数,我们的讲师给了我们返回值:     eval((eval [Num x,op,Num y])++ op_next:remaining_expr)

所以,如果有人可以提供帮助,如果你明白我说的话会有所帮助,哦,轻松一点,我还在努力学习! :) 本实验旨在教我们模式匹配,但我仍然不能完全理解它。

我可能应该注意到,我知道自己应该做什么,但却不知道如何正确地写它!

1 个答案:

答案 0 :(得分:-2)

哦,当然,是的,本周的实验室也让我发疯了。

我在9个案例中做到了这一点(我认为这很糟糕,我需要找到一个更好的方法,但它工作得很好)。

我所做的是设置涵盖所有可能输入的模式

  1. px:Num x:op:py:Num y:opn:r
  2. px:Num x:op:Num y:opn:r
  3. Num x:op:py:Num y:opn:r
  4. Num x:op:Num y:opn:r
  5. Num x:op:Num y:[]
  6. Num x:op:py:Num y:[]
  7. px:Num x:op:Num y:[]
  8. px:Num x:op:py:Num y:[]
  9. _
  10. 其中px和py是数字前缀(加号/减号)

    在情况2~3中,他们再次调用eval,处理到情况1,与情况5~7相同,他们将处理到情况8。所以情况1& 8是进行实际计算的情况。

    案例1是您处理binding_power函数(计算运算符优先级)的地方;

    案例8是您进行最终计算的地方(注意零分割),您可以设置一个where子句,比如翻译负数:

    tx = (if px == Minus then -1 else 1) * x
    ty = (if py == Minus then -1 else 1) * y
    

    如果您想要剧透,请点击以下链接:http://pastebin.com/Vq8PC6Z3