比计算单位列表的长度更好的方法

Dan*_*ton 6 haskell list idiomatic

我有时发现自己编写这样的代码:

someFunc :: Foo -> Int
someFunc foo = length $ do
  x <- someList
  guard someGuard
  return ()
Run Code Online (Sandbox Code Playgroud)

或等效地:

someFunc foo = length [() | x <- someList, someGuard]
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来执行这种计算?更高效?更具可读性?更惯用吗?

Dan*_*her 8

普里莫

guard someGuard
return ()
Run Code Online (Sandbox Code Playgroud)

是冗余的,如果条件为真则guard已经返回().然后我想someGuard实际上取决于x,否则它会if someGuard then length someList else 0.通常的写作方式是

someFunc foo = filter (\x -> someGuard) someList
Run Code Online (Sandbox Code Playgroud)

如果情况真的像你的例子看起来那么简单.对于更复杂的情况,使用您的示例样式之一是最直接的方式.如果事情变得非常复杂,我觉得这种做法更可取.


Nor*_*sey 6

如果您发现自己反复编程到模式,那么要做的是编写一个更高阶的函数来封装该模式.你可以使用你拥有的主体,但是为了完全确信你的代码没有分配,我建议使用foldl并严格应用增量运算符:

numberSatisfying :: Integral n => (a -> Bool) -> [a] -> n
numberSatisfying p = foldl (\n x -> if p x then (+1) $! n else n) 0
Run Code Online (Sandbox Code Playgroud)

我使用QuickCheck确认此代码与原始代码相同.(是的,QuickCheck将使用随机谓词进行测试非常酷.)

  • 为什么不`foldl'? (3认同)