[英]Trying to write a function in Haskell and according to -Wall I need a pattern that matches (_:_:_) _ What does this pattern mean and why do I need it?
So I wanted to try to make this function myself (multiples everything in a list by 3 and returns a new list): 因此,我想尝试自己制作此功能(将列表中的所有内容乘以3,然后返回一个新列表):
list = [1,2,3,4,5,6,7,8,9,10]
list2 = [3 * x | x <- list]
And I managed to get this using guards (basically it stops when x reaches the bound of the 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)
Then I decided to try to do it with pattern matching: 然后,我决定尝试通过模式匹配来做到这一点:
tripleMultList :: [Int] -> Int -> [Int]
tripleMultList [] x = []
tripleMultList [y] x | x == (length [y] - 1) = [y] !! x : []
tripleMultList [y] x = [y] !! x : tripleMultList [y] (x + 1)
But whenever I'd try to run this function I would get a non exhaustive pattern matching error so I checked ghci -Wall and it said that I needed a pattern matched to 但是每当我尝试运行此功能时,我都会得到一个非详尽的模式匹配错误,因此我检查了ghci -Wall并说我需要一个与
(_:_:_) _
which I assume would take the form of 我认为它将采取以下形式
tripleMultList (_:_:_) _ = something
I'm aware that 我知道
(_:_:_)
has to do with selecting elements from a list and separating them from the list itself, though I have no idea why this would apply to my function. 与从列表中选择元素并将其与列表本身分开有关,尽管我不知道为什么这会应用于我的函数。 I also don't know what "_" means or does and how it applies to my function either. 我也不知道“ _”的含义或作用以及它如何应用于我的函数。
So I guess my question is, what does this pattern mean and why do I need it when I have roughly the same thing in the version of my function which uses a guard and that one works fine? 所以我想我的问题是,这种模式的含义是什么,当我在使用防护的函数版本中具有大致相同的东西并且可以正常工作时,为什么需要它?
Your function takes two arguments. 您的函数有两个参数。 GHCI is telling you that you haven't provided a definition for a function call that follows the pattern GHCI告诉您尚未提供遵循该模式的函数调用的定义
tripleMultList (_:_:_) _
ie when the first argument matches the pattern _:_:_
and the second argument matches the pattern _
. 也就是说,当第一个参数匹配模式_:_:_
,第二个参数匹配模式_
。 The pattern _
matches everything. 模式_
匹配所有内容。 The pattern _:_:_
matches lists where the first element is anything, the second element is anything, and the rest of the list is anything. 模式_:_:_
匹配列表,其中第一个元素是任何东西,第二个元素是任何东西,列表的其余部分是任何东西。 In other words, _:_:_
matches lists of at least two elements. 换句话说, _:_:_
匹配至少两个元素的列表。
Look at the cases you defined: 查看您定义的情况:
tripleMultList [] x = []
tripleMultList [y] x | x == (length [y] - 1) = [y] !! x : []
tripleMultList [y] x = [y] !! x : tripleMultList [y] (x + 1)
That's: 那是:
x == (length [y] - 1)
is true. 仅当x == (length [y] - 1)
为true时。 This leaves out the case when the first argument is a list with at least two elements. 当第一个参数是一个至少包含两个元素的列表时,就省去了这种情况。
If you want to follow the decomposition in your first definition, then you need to use y
in the second and third definitions instead of [y]
. 如果要遵循第一个定义中的分解,则需要在第二个和第三个定义中使用y
而不是[y]
。 The pattern y
(a variable) matches anything (of the right type) and gives it the name y
. 模式y
(一个变量)匹配任何(正确类型的)东西,并为其命名为y
。 The pattern [y]
matches any list of one element and gives this element the name y
. 模式[y]
匹配一个元素的任何列表,并将该元素命名为y
。
You almost never want to use !!
您几乎永远都不想使用!!
, especially not for iterating over a list. ,尤其是不适用于遍历列表。 Remember the definition of a list: 记住列表的定义:
data [] a = [] | a : [] a
There are only two patterns you need to match: the empty list ( []
) and the non-empty list ( x:y
). 您只需要匹配两种模式:空列表( []
)和非空列表( x:y
)。 You have the empty-list case correct: multiplying every element of an empty list yields another empty list. 您的空列表大小写正确:将一个空列表的每个元素相乘会产生另一个空列表。
tripleMultList [] = []
For a non-empty list, you need something only slightly more complicated. 对于非空列表,您只需要稍微复杂一点即可。 You have the first element x
and the rest of the elements as y
. 您拥有第一个元素x
,其余元素为y
。 All you need to do is multiply x
by 3, and add it to the list produced by multiplying everything in y
by 3: 您所需要做的就是将x
乘以3,并将其添加到将y
的所有乘以3产生的列表中:
tripleMultList (x:y) = let x' = 3 * x
y' = tripleMultList y
in x' : y'
Note that we can generalize this for any operation on x
: 请注意,我们可以对x
上的任何操作进行概括:
doSomething :: (a -> b) -> [a] -> [b]
doSomething _ [] = []
doSomething f (x:y) = let x' = f x
y' = doSomething f y
in x' : y'
tripleMultList = doSomething (\x -> 3 * x)
This type of operation is so common that doSomething
is already defined in Haskell, but it is called map
instead. 这种操作非常普遍,以至于Haskell中已经定义了doSomething
,但是它被称为map
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.