如果我有这样的东西:
func (x1:x2:x3:xs) = xs
那么 x1,x2,x3
一定存在,是吗?
它们不能是 []
,但必须(再一次,必须)有一个值,是吗?
此外,xs
可以是 []
或 [a]
或 [a,a,a]
(等'), 是吗?
(在 [a]
中,我的意思是它是一个包含一个数字的列表,而 [a,a,a]
是三个数字的列表)。
我还有定义 isPrefixOf 的函数:
myIsPrefixOf :: (Eq a) => [a] -> [a] -> Bool
[] `myIsPrefixOf` [] = True
[] `myIsPrefixOf` (x:xs) = True
list `myIsPrefixOf` [] = False
(l:ls) `myIsPrefixOf` (x:xs) = if l == x then ls `myIsPrefixOf` xs
else False
如果我删除第一个模式,该函数将如下所示:
myIsPrefixOf :: (Eq a) => [a] -> [a] -> Bool
[] `myIsPrefixOf` (x:xs) = True
list `myIsPrefixOf` [] = False
(l:ls) `myIsPrefixOf` (x:xs) = if l == x then ls `myIsPrefixOf` xs
else False
现在我要写:
[] `myIsPrefixOf` []
我会得到:False(它应该是 True)。
是不是因为第一个模式在他的右边有元素:(x:xs)
,正因为如此,x
必须有一个值,所以我通过了第一个模式,然后进入第二个模式:
list `myIsPrefixOf` [] = False
哪个匹配,返回False。
我说得对吗?
如果我是对的,那么区别在于如果我写(x:xs)
,x
必须是一个值而不是[]
.
另一方面,如果我写 list
,它可以匹配 []
和 [a]
和 [a,a ,a]
(etc'),因此,第二个模式的 list
将匹配我输入中的第一个 []
,并且所以我会得到 False ?
(和以前一样,在 [a]
中,我的意思是它是一个包含一个数字的列表,而 [a,a,a]
是包含三个数字的列表)。
另外,为了纠正这种情况,我需要更换:
[] <code>myIsPrefixOf</code> (x:xs) = True
有了那个:
[] `myIsPrefixOf` list = True
现在是表达式:
[] `myIsPrefixOf` []
[] `myIsPrefixOf` [1,2,3]
将再次匹配:
[] `myIsPrefixOf` list = True
希望我在这些事情上是正确的,现在来回答另一个问题:
这是一开始的固定功能(应用更改后)
myIsPrefixOf :: (Eq a) => [a] -> [a] -> Bool
[] `myIsPrefixOf` list = True
list `myIsPrefixOf` [] = False
(l:ls) `myIsPrefixOf` (x:xs) = if l == x then ls `myIsPrefixOf` xs
else False
现在,如果我删除第二个模式匹配,该函数将如下所示:
myIsPrefixOf :: (Eq a) => [a] -> [a] -> Bool
[] `myIsPrefixOf` list = True
(l:ls) `myIsPrefixOf` (x:xs) = if l == x then ls `myIsPrefixOf` xs
else False
然后像这样调用函数:
[1,2] `myIsPrefixOf` [1]
我收到一条错误消息,指出函数中没有详尽的模式。
我想看看我是否明白为什么会这样。
该函数通过第一个模式并到达第二个模式:
(l:ls) `myIsPrefixOf` (x:xs) = if l == x then ls `myIsPrefixOf` xs
else False
所以:
[1,2] `myIsPrefixOf` [1]
和:
l == x
.
它们都是 1
,所以我再次匹配第二个模式:
(2:[]) `myIsPrefixOf` ([]:[])
现在,l == 2
,但是 x == []
因此,表达式:l == x
返回非穷尽模式...
是因为我正在尝试检查数字和列表之间的相等性吗?
相等参数 (==) 应该只检查相同类型的元素吗?
(即:'a' == 'b'
或 1 == 3
)
好吧,我明白了吗? :-)
非常感谢 :-)。
最佳答案
你对第一个问题的理解是正确的,但是你对第二个问题的理解是错误的。
要了解原因,请从实际功能退一步并查看列表。列表有两个构造函数,[]
和 :
。因此,完整的模式匹配需要涵盖这两种情况。
您的函数有两个列表参数,因此您需要涵盖 2 * 2 == 4
种情况。对于采用两个列表参数的函数,始终都是这种情况;如果您遗漏一个组合,您将收到某些输入的“非详尽模式”错误。这些是您在第一个版本中遇到的情况:
[] `f` [] = True
[] `f` (x:xs) = True
(l:ls) `f` [] = False
(l:ls) `f` (x:xs) = ...
当您避免在两个列表构造函数上进行模式匹配时,您可以将两种情况合并为一种情况。这就是您在第一个问题中所做的:
[] `f` list = True
...
在这里您将忽略第二个参数的细节——它是哪个列表构造函数并不重要。只要两种情况的答案相同,就可以像这样折叠它,在本例中就是这样。
对于你的第二个问题,你想放弃第三个案例。避免“非详尽模式”错误的唯一方法是使第四种情况不那么具体:
(l:ls) `f` xlist = ...
但随后您就卡住了,因为您无法再获取 xlist
的第一个元素,因为您不知道它不是空的。您可以执行 head xlist
,但这会在空列表上崩溃。所以实际上你必须先检查空列表:
(l:ls) `f` xlist = if null xlist then False
else if l == head xlist then ls `myIsPrefixOf` tail xlist
else False
但这太冗长了,原来的模式匹配更好。
你第二个问题具体出错的地方是手动执行isPrefixOf [1,2] [1]
。
the function pass through the first pattern and get to the second one:
(l:ls) `myIsPrefixOf` (x:xs) = if l == x then ls `myIsPrefixOf` xs else False
so:
[1,2] `myIsPrefixOf` [1]
and:
l == x.
到目前为止还不错。
they both 1, so i match again the second pattern:
等等,稍等片刻,找出这里的所有值。我们已经知道 l==x==1
。还有 ls==[2]
和 xs==[]
。
现在当我们重复出现时,ls
不会匹配第一个模式(它不是空的),但是 xs
不会匹配第二个模式(它是空的,并且(x:xs)
需要一个 :
对象,而不是 []
)。因此该函数因“非详尽模式”而崩溃。
关于haskell - 请帮助我理解 haskell 中的模式匹配。我有点困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2101740/