【问题标题】:Haskell Pattern Matching: Readability and PerformanceHaskell 模式匹配:可读性和性能
【发布时间】:2016-05-16 15:45:30
【问题描述】:

我正在阅读learn you a haskell 教程和 我一直在绊倒作者的一些例子 已经给了。

例如他重新实现了 zip 如下:

zip' :: [a] -> [b] -> [(a,b)]  
zip' _ [] = []  
zip' [] _ = []  
zip' (x:xs) (y:ys) = (x,y):zip' xs ys

他对所有其他示例都使用了类似的方法, 他把最具体的模式放在首位。这是一个略有不同的 zip函数的版本:

zip' :: [a] -> [b] -> [(a,b)]
zip' (x:xs) (y:ys)  = (x, y):zip' xs ys
zip' _ _            = []

据我了解,这两种方法都做同样的事情。如果 以 (x:xs) 或 (y:ys) 的方式提供一个空列表 将不匹配哪个将通过附加来完成递归 空列表 []。

  1. 我个人更喜欢第二个版本的可读性,但也许我这样做是错误的。
  2. 它对方法的性能有任何影响吗?据我了解,如果最上面的模式不匹配,Haskell 将检查下一个模式。模式的顺序会影响性能吗?

亲切的问候,

编辑:

可能重复: Haskell GHC: what is the time complexity of a pattern match with N constructors?

总结:模式的顺序对于语义(就参数的严格评估而言)和函数的可读性而言非常重要。模式匹配本身的时间复杂度总是 O(1)

【问题讨论】:

标签: haskell pattern-matching


【解决方案1】:

据我了解,这两种方法都做同样的事情。

几乎;有一个例外:

\> zip' undefined []   -- 1st definition of zip'
[]
\> zip' (filter (< 4) [1..]) [1, 2, 3]
[(1,1),(2,2),(3,3)]

而:

\> zip' undefined []   -- 2nd definition of zip'
*** Exception: Prelude.undefined
\> zip' (filter (< 4) [1..]) [1, 2, 3]
[(1,1),(2,2),(3,3)   -- gets stuck here; never returns

换句话说,第二个定义总是对 both 参数强制使用weak head normal form

性能方面,这意味着可以构造一个病态的示例,使得 WHNF 涉及大量计算,因此一个定义的执行方式与另一个定义非常不同。

【讨论】:

  • 确实如此。但是zip' undefined [1, 2, 3] 在这两种情况下都会产生异常。所以我看不出这有什么帮助,或者说为什么它是可取的。
  • @Nimi,在这种情况下,它只确定哪个参数是无条件严格的。
  • @Nimi 的重点是您可以使这两个函数的行为非常不同,而不是做同样的事情。请注意另一个示例,zip' (filter (&lt; 4) [1..]) [1, 2, 3],看看这也会如何影响性能。
  • @behzad.nouri Ahh.. 我现在可以看到了。谢谢
猜你喜欢
  • 2011-06-13
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多