【问题标题】:Does Haskell allow a let expression for multiple pattern matchings?Haskell 是否允许 let 表达式用于多个模式匹配?
【发布时间】:2013-03-14 19:48:48
【问题描述】:

假设我有一个函数可以进行一些计算,有几种模式;以模式匹配的形式实现。

这些模式中的大多数(以及其他不同的东西)对参数进行处理,为此我在let 表达式中使用中间变量。但是我发现在许多模式上使用相同的let 确实是多余的,我想知道是否有一种方法可以为多个模式定义一个let

这是我重复的let 的示例:

data MyType a = Something a | Another Int [a]

myFunc (Something x) = -- return something, this isn't the point here
myFunc (Another 0 xs) =
    let intermediary = some $ treatment xs
    in doSthg intermediary 1 
myFunc (Another 1 (x:xs)) =
    let intermediary = some $ treatment xs
    in doSthg1 intermediary 1 x
myFunc (Another 2 (x:x':xs)) =
    let intermediary = some $ treatment xs
    in doSthg2 intermediary 2 x x'

您可以看到,当我将参数xs 用于intermediary 时,它始终存在,这可以被分解。 它可以通过使用辅助函数轻松实现,但我想知道如果没有辅助函数,我的要求是否可行。对于初学者,请尽量保持简单,我希望我的例子足够清楚。

【问题讨论】:

  • 不!必须使用单独的函数并将其作为参数显式传递以排除重复的代码。就 Haskell 而言,以上出现的xs 是完全不同的变量(因为它们有不同的绑定位点)。
  • 谢谢!现在我有另一个问题:你是否打算让第三个和第四个方程永远不匹配?因为xs 匹配任何列表...您是否颠倒了方程式的顺序?
  • 我写这个是为了说明xs是从模式匹配中提取的几个模式,但并不总是具有相同的含义(否则模式匹配将没有兴趣:只有一个图案)。在示例中用它做了什么并不重要。但在我的代码中,y 被替换为实际值,因此后面的模式匹配。但你又是对的,所以我将用具体的类型对其进行编辑,以使整个事情更容易理解。

标签: haskell functional-programming pattern-matching let


【解决方案1】:

这个特殊的问题可以解决如下:

myFunc2 (Something x) = returnSomething x
myFunc2 (Another n ys) = 
    let xs = drop n ys
        x = head ys 
        x' = head (tail ys)
        intermediate = some $ treatment xs 
    in case n of
        0 -> doSomething intermediate n
        1 -> doSomething1 intermediate n x
        2 -> doSomething2 intermediate n x x'

感谢惰性评估 xx' 只有在需要它们的值时才会被评估。

然而 - 这是一个很大的然而! - 当您尝试调用myFunc2 (Another 2 [])(如果doSomething2 实际使用x!)时,您的代码将给出运行时错误,因为要找出x 是什么,我们需要评估head ys - 那'会因空列表而崩溃。您作为示例提供的代码对于Another 2 [] 也不起作用(另一个运行时错误),因为没有匹配的模式,但提供后备案例更容易。

如果您控制输入并始终确保Another 中的列表足够长,这可能不是问题,但请务必注意此问题!

【讨论】:

  • 这在我的代码中实际上不是问题,因为Another 对象不能用空列表构建。 +1,效果很好
  • @tehinternetsismadeofcatz:整个问题就像一个强大的“堆栈语言的解释器”——感觉它,所以如果你编译正确,你就会运行正确——类型系统不是(但它是关闭!)足够强大,可以表达您对输入的知道。您也可以考虑更改您的 MyType 以更清楚地表达您对论点的了解,但这需要大量工作......
猜你喜欢
  • 1970-01-01
  • 2018-08-06
  • 2017-10-08
  • 1970-01-01
  • 2023-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-07
相关资源
最近更新 更多