【问题标题】:Why can't I pattern match on the concatenation function (++) in Haskell?为什么我不能在 Haskell 中的串联函数 (++) 上进行模式匹配?
【发布时间】:2015-12-11 19:19:27
【问题描述】:

我正在尝试在函数 Split 中匹配 **String Newline String** 模式。

split::String -> [String]
split[] = []
split (x++'\n':xs) = [x]++split(xs)

我收到此错误: Parse error in pattern: x ++ ('\n' : xs)

我在这里做错了什么?

我知道还有其他方法可以达到相同的结果,但我想了解这种模式有什么问题。顺便说一句,我对 Haskell 还很陌生。

【问题讨论】:

  • 您只能在构造函数上进行模式匹配。正如你所说,++ 是一个函数。
  • 如果你能详细解释你想让你的函数做什么,那将是非常有帮助的。你写的代码好像没有多大意义,所以我说不出来。
  • 好问题!早在 89 年,我构建了一种语言,它实际上允许 elem x (_ ++ x : _) = True; elem _ _ = 错误。我想念它。
  • @pigworker 库里怎么样?
  • @ErikAllik 寻找可以窃取的想法总是值得的。我当然希望看到我们碰巧在功能上呈现的关系的输入输出模式更具流动性。

标签: haskell pattern-matching


【解决方案1】:

一个问题(据我所知)是++ 不像: 那样是列表数据类型的构造函数。你可以认为列表数据类型被定义为

data [a] = [] | a : [a]

其中: 是一个将元素附加到列表前面的构造函数。但是,++ 是一个函数(在此处的文档中定义:http://hackage.haskell.org/package/base-4.8.1.0/docs/src/GHC.Base.html#%2B%2B)为

(++) :: [a] -> [a] -> [a]
(++) []     ys = ys
(++) (x:xs) ys = x : xs ++ ys

我们可以定义自己的数据类型列表,比如

data List a = Empty | Cons a (List a)

这将模仿我们熟悉的列表的行为。事实上,您可以在模式中使用(Cons val)。我相信你也可以像这样使用 concat 构造函数定义一个类型

data CList a = Empty | Cons a (CList a) | Concat (CList a) (CList a)

您可以使用它来延迟连接两个列表并延迟将它们合并为一个。使用这种数据类型,您可以对 Concat xs ys 输入进行模式匹配,但您只能在两个列表的边界上工作,而不是在一个列表的中间。

无论如何,我自己对 Haskell 还是很陌生,但我希望这是正确的。

【讨论】:

  • 谢谢。我有点惊讶的是,没有多少关于 Haskell 的资料清楚地定义了模式的构成。阅读您的答案后,我查找了函数的模式匹配并找到了this。它清楚地提到模式匹配仅适用于构造函数。它还使用 (++) 函数来证明任意函数不能在模式中使用。
  • 为了后代,模式匹配的形式语义在Haskell report中定义。
  • @farhanhubble 我相信你要么在关注一个非常糟糕的来源,要么你没有正确阅读它。 AFAIK 所有好的来源都会清楚地解释这一点。
  • @farhanhubble:另一种说法是,当你声明一个数据类型时,你会得到一个值构造函数和一个模式构造函数(或值解构器)。当你定义一个函数时,你只会得到值的构造函数。
  • 有趣的观点@Simon Shine。我使用Real World Haskell 作为主要来源,虽然它在代数数据类型和构造函数的上下文中引入了模式匹配,但它没有详细说明模式匹配是特定于它们的。
【解决方案2】:

想象一下,你可以。然后匹配"a\nb\nc" 可以产生x = "a", xs = "b\nc"x = "a\nb", xs = "c",您需要一些临时规则来决定使用哪个。一般来说,函数匹配也是不可能合理实现的:你需要在给定f x的情况下找到一个x,除了尝试所有可能的x之外别无他法。

【讨论】:

  • 谢谢@Alexey Romanov。我认为歧义是一个原因,但预计会出现更详细的错误消息,例如 Haskell 在其他歧义的情况下显示的错误消息。
  • @farhanhubble 逻辑基本上是:因为这些问题,你无法在函数上匹配,只能在构造函数上匹配;因此尝试检查特定功能是否会给您带来歧义是没有意义的。相反,模式的语法规则被定义为需要构造函数,因此您会收到解析错误。不过,可能会有更好的消息说 ++ 不是构造函数。
  • 歧义甚至不是最大的问题,imo。最大的问题可能是函数匹配相当于解决停机问题,并且(相当于)需要能够在有限时间内枚举无限域。
  • @ReinHenrichs 是的,这就是我在第三句话中所说的。
  • 但是++ 不仅仅是任何旧功能。这是 sublist-in-list 拉链的“插件”功能。在一阶归纳数据结构中,候选空间分解是可搜索的。仍然存在优先搜索的问题,程序员必须以某种方式做到这一点。一种方法是仅当函数在某些 MonadPlus 中进行计算时才允许模式中的歧义。这样,上下文决定如何解释匹配期间发出的选择信号。所以我认为现在决定这不值得考虑还为时过早。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-16
  • 2016-04-26
  • 1970-01-01
  • 2018-08-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多