【问题标题】:Pattern matching (x:_): why is the list head bounded to x?模式匹配(x:_):为什么列表头有界到 x?
【发布时间】:2016-11-27 09:44:13
【问题描述】:

只是在这里与 Haskell 苦苦挣扎...我有一个非常糟糕的术语,并且鉴于我的母语不是英语,因此进行正确的搜索有点复杂:P 我正在关注一些 Haskell 教程/书籍(向你学习Haskell,Real World Haskell,Happy Learn Haskell,还有一个邮件列表和一些随机页面),现在我停在这里:

head' :: [Char] -> Char
head' (x:_) = x

这个函数接收一个字符串类型的元素列表,如果我这样应用它:

head' "hello"

它返回“h”,它以x为界,“ello”以_为界,但没关系,因为我不使用它。我知道 (:) 函数(或用作中缀运算符)接收一个将被放置的元素和一个新列表的开始,其尾部将是另一个接收到的元素: 'a' : ['b', 'c'] 将返回 "abc" 但是,为什么当我在括号内使用 ":" 时,第一个元素绑定到 x 而其余元素绑定到 _?这里发生了什么?

我读了一些类似(x:xs) pattern Haskell logic 和这个(我认为更接近于回答我的问题)What does (x:_) and [x:_] mean? 的 SO 问题,但最后一个接受的问题说: ": 是列表的构造函数,它将新列表的头部作为左参数,尾部作为右参数。如果你将它用作像这里这样的模式,这意味着你匹配的列表的头部被赋予右边的图案和左边的尾巴。"

“列表的头部在右侧,尾部在左侧”......这真的让我感到困惑:如果使用时将头部赋予“_”而尾部赋予“x”“: " 关于模式匹配,为什么 x 有列表头的值?

我想可能是我的英语水平不好,这让我很难掌握这一点。我也会感谢一些提示(例如特定搜索)而不是直接答案。


编辑:对于像我这样的另一个菜鸟......正如接受的答案所说,“abcd”只是'a':'b':'c':'d',模式(x:_)匹配'a':'b' 以此类推,下划线表示“我不关心其余的”,并接收其余字符。就是这样:)

【问题讨论】:

  • 一定是打错了,左边的部分必须和列表的头部匹配。
  • 那是一个错字。现在已经修好了。
  • @EarlGray 好吧,我现在感觉好多了,我想哈哈。但我还是不明白:为什么尾巴被限制在 上? Haskell 会自动读取“(x:)”并说“好吧,我将头部绑定到 x,其余的绑定到 ”?或者“:”用于括号之间的模式匹配时有不同的含义?因为 (x:) 对于我的理解是“将 x 放在 _ 的开头”......这可能是一个愚蠢的问题,抱歉 :)
  • @sepp2k 谢谢你 :)
  • @EarlGray,在 Haskell 中,模式匹配绝对是 not 语法糖。相反,它是检查数据的最基本方法。事实上,Haskell 中的模式匹配被编译成 GHC 中间语言中的模式匹配,并且一直存在到代码生成! if/then/else 表单和守卫语法糖,并编译为模式匹配。

标签: haskell pattern-matching


【解决方案1】:

列表数据类型定义如下:

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

这意味着as 的列表要么是空的,要么是使用: (cons) 构造函数附加到尾部元素的头部元素。

当您对列表进行模式匹配时,您可以为这两种情况中的每一种情况定义您的函数。在head' 的情况下,当给定一个空列表时它只会失败,所以我们只匹配一种情况:a : [a] 情况。

如果你调用了head' "hello"(因为它现在存在,包括类型签名)它应该会失败,因为"hello" 实际上是String——Haskell 中[Char] 的别名。 "hello" 只是以下结构的语法糖:

"hello" = 'h':'e':'l':'l':'o':[]

因此,当您使用head' 对列表进行模式匹配时,您会在第一个: 的左侧得到'h',并且列表的其余部分(我们不关心)绑定到_.

【讨论】:

  • 类型签名有错字,我的电脑里有原始代码,所以我没有复制粘贴。现在已经修好了,抱歉:)
  • 经过一些编码和重新阅读您的问题和 EarlGray 的问题后,我想我明白了 :) 非常感谢您。非常感谢您的帮助:)
  • data [a] = [] | a : [a] 的有效性如何?我无法在 ghci 中做类似的事情:data TestType = Integer | Integer : [Integer]
  • @LanceClark 列表很特别,语言(好吧,GHC)会为您处理这个特定的定义。不过,您可以重新定义同构类型,如下所示:data List a = Nil | Cons a (List a)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-11
  • 2012-04-13
  • 1970-01-01
  • 2014-01-30
  • 2022-11-20
  • 1970-01-01
相关资源
最近更新 更多