在Haskell中合并两个排序列表 - 这些算法之间的区别是什么

时间:2014-03-31 10:43:16

标签: list haskell merge sorted sortedlist

我试着理解,后两种算法的区别是什么。

第一个(合并)效果很好,但是当我尝试将算法转换为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))

2 个答案:

答案 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],即返回x1 {{1}}将丢失。

答案 1 :(得分:1)

最后两个解决方案之间的区别在于merge'有一个死分支z == [] - 考虑到z@(x:xs),这个条件永远不会成立。

版本merge''错误地工作 - 如果您尝试其他输入,它会在某些时候点z==[]