所以我想尝试自己制作这个函数(将列表中的所有内容乘以 3 并返回一个新列表):
list = [1,2,3,4,5,6,7,8,9,10]
list2 = [3 * x | x <- list]
我设法使用守卫来得到这个(基本上当 x 到达列表的边界时它会停止):
tripleMultList :: [Int] -> Int -> [Int]
tripleMultList lst x
| null lst = []
| length lst - 1 == x = (lst !! x * 3) : []
| otherwise = (lst !! x * 3) : tripleMultList lst (x + 1)
然后我决定尝试使用模式匹配来实现:
tripleMultList :: [Int] -> Int -> [Int]
tripleMultList [] x = []
tripleMultList [y] x | x == (length [y] - 1) = [y] !! x : []
tripleMultList [y] x = [y] !! x : tripleMultList [y] (x + 1)
但是每当我尝试运行这个函数时,我都会收到一个非详尽的模式匹配错误,所以我检查了 ghci -Wall ,它说我需要一个与
匹配的模式(_:_:_) _
我认为会采取以下形式
tripleMultList (_:_:_) _ = something
我知道
(_:_:_)
与从列表中选择元素并将它们与列表本身分开有关,尽管我不知道为什么这适用于我的函数。我也不知道“_”的含义或作用以及它如何应用于我的函数。
所以我想我的问题是,这种模式意味着什么?当我的函数版本中有大致相同的内容且使用防护且工作正常时,为什么我需要它?
最佳答案
您的函数有两个参数。 GHCI 告诉您,您尚未提供遵循该模式的函数调用的定义
tripleMultList (_:_:_) _
即当第一个参数与模式 _:_:_
匹配并且第二个参数与模式 _
匹配时。模式 _
匹配所有内容。模式 _:_:_
匹配第一个元素是任何内容、第二个元素是任何内容、列表的其余部分是任何内容的列表。换句话说,_:_:_
匹配至少两个元素的列表。
看看您定义的情况:
tripleMultList [] x = []
tripleMultList [y] x | x == (length [y] - 1) = [y] !! x : []
tripleMultList [y] x = [y] !! x : tripleMultList [y] (x + 1)
那就是:
- 第一个参数:空列表;第二个参数:任何东西。
- 第一个参数:包含单个元素的列表;第二个参数:任何东西;仅当
x == (length [y] - 1)
为 true 时。 - 第一个参数:包含单个元素的列表;第二个参数:任何东西;仅当不满足上述条件时。
这忽略了第一个参数是至少包含两个元素的列表的情况。
如果您想遵循第一个定义中的分解,那么您需要在第二个和第三个定义中使用 y
而不是 [y]
。模式y
(变量)匹配任何内容(正确类型)并为其指定名称y
。模式 [y]
匹配一个元素的任何列表,并为该元素指定名称 y
。
关于list - 尝试在 Haskell 中编写一个函数,根据 -Wall 我需要一个匹配的模式 (_ :_:_) _ What does this pattern mean and why do I need it?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50650842/