我试着理解,后两种算法的区别是什么。
第一个(合并)效果很好,但是当我尝试将算法转换为Guarded表示法(merge')时,我得到了一个"非详尽的模式......"异常。
但为什么第三个版本(合并'')有效?它几乎与合并一样,必须有一些我不理解的列表(x:xs)。
1 -- merges two sortedists
2 merge xs [] = xs
3 merge [] ys = ys
4 merge (x:xs) ys
5 | x <= head ys = x : (merge xs ys)
6 | otherwise = head ys : (merge (x:xs) (tail ys))
7
8 -- merges two sorted lists (fails with exception)
9 merge' z@(x:xs) ys
10 | ys == [] = z
11 | z == [] = ys
12 | x <= head ys = x : (merge' xs ys)
13 | otherwise = head ys : (merge' (x:xs) (tail ys))
14
15
16 -- merges two sorted lists (exept the last element of the first list)
17 merge'' z@(x:xs) ys
18 | ys == [] = z
19 | xs == [] = ys
20 | x <= head ys = x : (merge'' xs ys)
21 | otherwise = head ys : (merge'' (x:xs) (tail ys))
答案 0 :(得分:5)
在merge'
和merge''
中,您假设第一个参数的格式为x:xs
,这会排除空列表,并导致问题。
例如
head z@(x:xs) = x
调用1
时,会按预期生成head([1,2,3])
,但head([])
会抛出Non-exhaustive patterns in function head
例外,因为[]
与x:xs
不匹配( @
在这里并不重要。)
特别是,这意味着在merge'
中,z == []
案例永远无法匹配,如果您拨打merge''
,merge [] [1,2,3]
也会引发异常。
另请注意,merge''
xs == []
案例merge'' [1] [2]
存在问题。例如,如果我们调用[1]
,则会匹配此案例,因为1:[]
为ys
。然后,只返回[2]
,即返回x
,1
{{1}}将丢失。
答案 1 :(得分:1)
最后两个解决方案之间的区别在于merge'
有一个死分支z == []
- 考虑到z@(x:xs)
,这个条件永远不会成立。
版本merge''
错误地工作 - 如果您尝试其他输入,它会在某些时候点z==[]
。