【问题标题】:Get the sum and product of integres defined in a tree获取树中定义的整数的总和和乘积
【发布时间】:2011-05-06 01:16:14
【问题描述】:

我在理解如何在 Haskell 中执行以下操作时有点问题:

假设我有一个类似的声明:

  • a * (b + c)
  • a + (b * c)
  • a + (b * ( c + d))
  • a * (b + ( c * d))
  • 等。等

我想在树中表达这些语句并评估每个语句的结果,对于初学者,我定义了以下数据结构:

data statement = Number Int 
               | Product statement statement 
               | Sum statement statement
               deriving (Eq, Show)

对于一个可以使用的示例树,我使用了以下函数:

a :: statement
a = Product (Number 2) (Sum (Number 5) (Number 1))

现在我想构建一个函数 treeResult,它给我定义的语句的结果,但我不知道如何解决这个问题。上述语句返回的整数应该是 12。

我的第一个猜测是编写一个将“语句”作为参数并返回一个 int 的函数,对于初学者来说只能使用简单的语句。

treeResult :: statement -> Int
treeResult (Number a) = a
treeResult (Product (Number a) (Number b)) = a*b
treeResult (Sum (Number a) (Number b)) = a+b

现在我知道我需要一些可以递归的东西,但我不知道如何在 haskell 中编写它,请问有人可以帮我吗?

【问题讨论】:

    标签: haskell recursion functional-programming expression-trees


    【解决方案1】:

    首先:statement 需要大写,因为它不是类型变量。但这是最不重要的。

    treeResult :: Statement -> Int
    treeResult (Number x) = x
    

    到目前为止显然是正确的。我们正在匹配 Number 构造函数,提取 Int 并返回它 - 类型正确并执行应有的操作。

    treeResult (Product (Number a) (Number b)) = a*b
    treeResult (Sum (Number a) (Number b)) = a+b
    

    这是很好的类型,但它不够通用。在此模式中,您将ProductSum 的字段限制为Numbers,但实际上它们可以是任何Statement。所以你需要定义Product/Sum:

    treeResult (Product a b) = ...
    treeResult (Sum a b) = ...
    

    但我们不能只是将两个Statements 相加/相乘。 (+)(*) 没有为它们定义(我们现在正在这样做)。当一个操作数是Product 时,我们如何获得它作为Int 的值?通过评估它。 Statement是递归的,所以我们需要递归来求值。这样,函数就变成了

    treeResult (Product a b) = (treeResult a) * (treeResult b)
    treeResult (Sum a b) = (treeResult a) + (treeResult b)
    

    【讨论】:

    • 那非常详细,这将有助于任何偶然发现相同问题的人。非常感谢您的宝贵时间。
    【解决方案2】:
    treeResult (Sum statement1 statement2) = treeResult statement1 + treeResult statement2
    

    产品类似。这只是认识

    • (a + b) 的结果 == a 的结果 + b 的结果

    (顺便说一句,数据类型应该称为Statement,带有大写的S。

    data Statement = Number Int | Product Statement Statement | Sum Statement Statement
                     deriving (Eq, Show)
    

    )

    【讨论】:

    • 那是完全错误的。 (编辑:好的,现在它是正确的 - 但我仍然不会投票,因为它缺乏任何解释)
    • 我从来没有想过会这么简单。非常感谢您的帮助:)
    猜你喜欢
    • 1970-01-01
    • 2016-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多