【问题标题】:Haskell, function for solving basic equationsHaskell,求解基本方程的函数
【发布时间】:2015-05-25 07:49:05
【问题描述】:

我是 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 [数字 3.2,加号,减号,数字 4.2,减号,数字 5.3,加号,数字 6.3] [数量 {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 因为它是双精度的,现在我不确定这是否正确。 虽然我知道这不是详尽无遗的,因为我没有考虑到所有的可能性。 我需要帮助的是考虑负数,例如减号,加号应该返回减号,但我还需要注意顺序的工作原理,例如幂,然后是乘法/除法,然后是加法/减法。 如果调用 eval 函数,我们的讲师已经给了我们返回值: eval ((eval [Num x, op, Num y]) ++ op_next: remaining_expr)

因此,如果有人可以提供帮助,如果您明白我在说什么,那将很有帮助,哦,放轻松,请我仍在努力学习! :) 这个实验室旨在教我们模式匹配,但我仍然没有完全理解它。

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

【问题讨论】:

  • 考虑将其匹配为(Num x : op : Num y : op_next : remaining_expr)。您可以进行更改,并且不会影响您的功能当前的工作方式。然后开始思考你可以用op_nextremaining_expr 做什么。如果您需要担心操作顺序,那么请考虑您可以使用哪种模式匹配来查找这些情况。不同运营商之间有哪些不同的交互方式?确保[Num 1, Plus, Num 2, Times, Num 3] 被视为1 + (2 * 3)。让那个工作,然后实施下一个规则。看看你能不能找到一个模式。
  • 我投票决定将此问题作为题外话结束,因为它专门用于特定的家庭作业并且不清楚。

标签: list haskell math recursion pattern-matching


【解决方案1】:

哦,你好同学,是的,这周的实验室也让我发疯了..

我在 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. _

其中 px 和 py 是数字前缀(加/减)

在 case 2 ~ 3 中,他们会再次调用 eval 来处理 case 1,与 case 5 ~ 7 一样,他们会处理 case 8。所以 case 1 & 8 是进行实际计算的 case。

案例 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

【讨论】:

  • 嘿,谢谢伙计,现在这很有意义,我知道我理解它,只是没有通过我的脑海。但我肯定会按照自己的方式做,但我非常感谢你的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多