如何避免不必要的计算?

Bis*_*ath 5 optimization haskell list

如果测试在列表中超过3个元素失败,我需要返回false.有什么我可以做的优化吗?

isItemOk :: Integer -> Boolean 
isItemOk = ( some costly opernation )
Run Code Online (Sandbox Code Playgroud)

这是我想要优化的功能,

isListOk :: [Integer] -> Boolean 
isListOk = 3 >= sum ( [ 1 | x <- [1.1000], isItemOk x ])
Run Code Online (Sandbox Code Playgroud)

我尝试优化,假设它找到4个元素将不会寻找更多.

isListOk :: [Integer] -> Boolean 
isListOk = 3 >= sum ( take 4 [ 1 | x <- [1.1000], isItemOk x ])
Run Code Online (Sandbox Code Playgroud)

谢谢.

C. *_*ann 8

您可以使用filter检查失败元素的内容,然后take 4查看您拥有的元素数量length.

懒惰的评估意味着在找到这四个之后它不会费心检查任何东西,所以你已经完成了.当然,如果三个或更少元素的测试失败,它将检查整个列表,但是你无能为力.

避免的重要一点是"计算未通过测试的元素",或"过滤然后得到结果的长度",或类似的东西.首先不使用take或类似的东西,这样做会强制检查整个列表.这是null通常给初学者的"使用或模式匹配以检查空列表" 的更通用版本.但看起来你已经避免了这个错误!


ham*_*mar 6

对于像3这样的低数字,您可以使用模式匹配.

case filter isItemOk xs of
   x1 : x2 : x3 : _ -> ...
   _                -> ... 
Run Code Online (Sandbox Code Playgroud)


Dan*_*ner 5

我想借此机会大肆宣传懒惰的自然数.使用这个库genericLength,我们可以写

import Data.Number.Natural
import Data.List
isListOk = (3 :: Natural) >= genericLength (filter isItemOk [1..1000])
Run Code Online (Sandbox Code Playgroud)

并且它不会再做任何工作了:这个函数在返回之前最多可以找到四个好的项目.例如:

> (3 :: Natural) >= genericLength (filter even (2:4:6:8:undefined))
False
Run Code Online (Sandbox Code Playgroud)