HASKELL字符串与Head $ Filter和Head $ Drop之间有性能差异吗?



我正在研究Haskell中"人"对象的列表,我想知道head$dropWhilehead$filter之间的性能是否有任何差异,以找到具有给定名称的第一人。数据类型的两个选项和剪辑将是:

datatype Person = Person { name :: String
                         , otherStuff :: StuffTypesAboutPerson }
findPerson :: String -> [Person] -> Person
findPerson n = head $ dropWhile (p -> name p /= n)
findPerson n = head $ filter (p -> name p == n)

我的想法是,filter必须将n的全长与每个name的全长进行比较,直到找到第一个。我认为dropWhile只需要比较字符串,直到第一个非匹配Char。但是,我知道Haskell有很多魔术,尤其是GHC。我更喜欢使用filter版本,因为我认为阅读更直接。但是,我想知道是否有任何性能差异?即使它可以忽略不计,我也从好奇心的角度看我也很感兴趣。

编辑:我知道我还需要保护Maybe等错误,但我遗漏了以简化代码示例。

问题有几种方法

findPerson n = head $ dropWhile (p -> name p /= n)
findPerson n = head $ filter (p -> name p == n)
findPerson n = fromJust $ find (p -> name p == n)

这个问题还指出了两个事实:

  • x,y是平等的字符串时,==需要比较所有字符
  • x,y是不同的字符串时,/=只需要比较直到第一个不同的字符

这是正确的,但不考虑其他情况

  • x,y是平等的字符串时,/=需要比较所有字符
  • x,y是不同的字符串时,==只需要比较直到第一个不同的字符

因此,在==/=之间没有绩效冠军。我们可以预期,其中一个最多将执行额外的not W.R.T.另一个。

另外,所有上面提到的findPerson的三个实现基本上执行相同的步骤。给定xs :: [Person],它们将全部扫描xs,直到找到匹配名称为止,而没有。在比赛前的所有人员中,名称将与n进行比较,并且该比较将停止以第一个不同的字符(无论我们在上面使用哪种比较)。匹配的人将与n(同样在所有情况下)将其名称完全比较。

因此,预计方法将同时运行。它们之间可能有很小的差异,但是它可能很小,以至于很难检测到。您可以尝试使用criterion进行实验,看看会发生什么,如果您愿意。