Haskell为什么使用@(as)

Haskell为什么使用@(as),haskell,pattern-matching,Haskell,Pattern Matching,遇到这个例子: buildEntry ws@(w:_) = (w, length ws) 使用ws@(w:)而不是: buildEntry' (w:ws) = (w, length (w:ws)) 因为我只是一个初学者,所以我认为第二个示例的可读性也更好。删除as模式并不总是可以提高可读性。比较 foo x@(C a b (D c d) (E e f)) = bar x 与 我认为第一个更具可读性 此外,可能存在一些性能差异。据我所知,使用x@(C…,然后稍后引用x,将使GHC将x定义为指

遇到这个例子:

buildEntry ws@(w:_) = (w, length ws)
使用
ws@(w:)
而不是:

buildEntry' (w:ws) = (w, length (w:ws))

因为我只是一个初学者,所以我认为第二个示例的可读性也更好。

删除as模式并不总是可以提高可读性。比较

foo x@(C a b (D c d) (E e f)) = bar x

我认为第一个更具可读性

此外,可能存在一些性能差异。据我所知,使用
x@(C…
,然后稍后引用
x
,将使GHC将
x
定义为指向持有
(C…
)的相同存储单元的指针。相反,使用具有相同参数的
(C…
)可以分配一个新的“对象”,它是原始对象的副本

当然,GHC可能会应用某种CSE(公共子表达式消除)来只保留一个副本。然而,由于CSE并不总是有益于w.r.t.性能,GHC在使用CSE时相当保守


现在,我看不出在这种特定情况下进行优化会有什么问题,所以GHC可能最终会使用CSE。尽管如此,我还是不确定这一点。

根据Richard Bird对Haskell的功能性思考:
与其解构一个列表,然后再重新构建它(一个廉价但非免费的操作),不如重用我们匹配的值。
ghc真的会在这里重构整个列表吗?似乎是一个微不足道的重写规则,我想主要是为了可读性。简单的懒惰就是不想输入更多的字符。我同意收益是最小的,在这种情况下可能是有争议的,但是如果你正在解构一个更复杂的数据结构呢。他们都必须在列表上进行模式匹配工作;最大的区别在于列表的哪些部分有名字。对于
length
,你不能犯这样的错误(尽管可能很愚蠢),比如为
w:w:ws
构建一个不正确的参数,因为“构建”该参数的工作已经在左侧完成,在左侧,你只能解构一个列表,而不能构建一个新列表。@chepner同意。代码应该是清晰和直接的,它是如何操作的。重建相同的值会混淆这一点,而“是”容易出错。我认为,更可能的错误是调用
length ws
。第一个错误也可以写成
foox@(C_uuud(E_uuu))=bar x
,让您专注于所涉及的构造函数,因为模式匹配并不关心它们的参数。但这只是为了举例说明。我有很多例子,我确实使用了一些或所有的参数,还需要在调用中传递完整的结构。另一个重要的区别是,第二个版本充满了引入错误的可能性。第一个版本说,我们将把
x
全部传递到
条中;第二个版本说,我们正在将类似于
x
的东西传递到
bar
中,但它可能在某些方面有所不同。
foo (C a b (D c d) (E e f)) = bar (C a b (D c d) (E e f))