Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell &引用;“同时”;列表的最小值和最大值_Haskell - Fatal编程技术网

Haskell &引用;“同时”;列表的最小值和最大值

Haskell &引用;“同时”;列表的最小值和最大值,haskell,Haskell,此函数返回一个2元组,其中包含列表的最小值和最大值: import Control.Arrow ((***), (>>>), (&&&)) import Data.Semigroup (getMin, getMax, Min(..), Max(..)) bounds :: (Bounded a, Ord a) => [a] -> (a,a) bounds = foldMap (Min &&& Max) >>

此函数返回一个2元组,其中包含列表的最小值和最大值:

import Control.Arrow ((***), (>>>), (&&&))
import Data.Semigroup (getMin, getMax, Min(..), Max(..))

bounds :: (Bounded a, Ord a) => [a] -> (a,a)
bounds = foldMap (Min &&& Max) >>> getMin *** getMax
例如:

> x = [1..10 :: Int]
> bounds x
(1,10)
它是否比
(最小x,最大x)
更有效


或者有没有比
(最小x,最大x)
更有效的方法?

首先,您的两个函数的行为并不相同<当
xs
为空列表时,code>(最小xs,最大xs)失效

它是否比
(最小x,最大x)
更有效

他们都是O(n),但回答这样的问题的唯一方法是在竞争中对他们进行基准测试。我想我希望
foldMap
解决方案会更快,因为它只对列表进行一次遍历,但让我们来看看

import Control.Arrow ((***), (>>>), (&&&))
import Data.Semigroup (getMin, getMax, Min(..), Max(..))
import System.Random
import Criterion.Main

bounds1, bounds2 :: (Bounded a, Ord a) => [a] -> (a,a)
bounds1 = foldMap (Min &&& Max) >>> getMin *** getMax
bounds2 xs = (minimum xs, maximum xs)

randomList :: Int -> IO [Int]
randomList count = take count <$> randoms <$> newStdGen

mkBench n = env (randomList n) $ \list -> bgroup (show n) [
    bench "foldMap" $ nf bounds1 list,
    bench "minMax" $ nf bounds2 list
    ]

main = defaultMain $ map mkBench [100, 1000, 10000, 100000, 1000000]

因此,
(最小xs,最大xs)
折叠映射
的思想要快得多。

折叠映射方法使用一个在整个遍历过程中不强制的盒装对。它将分配多于两次传递的方法,并且不允许对输入进行gc'd。失去/失去。@Carl很有趣,谢谢你。你认为明智地使用
某个地方可以解决性能问题?可能值得尝试使用严格的元组类型,而不是&&&我认为如果不在足够严格的对类型上使用类似于
Endo
的东西,您实际上无法从
foldMap
中获得良好的行为。
[]
foldMap
定义将以错误的方向关联。您需要重新关联函数传递以获得良好的空间使用。感谢您的基准测试!我知道
criteria
,但它在Windows上运行不太好(至少上次我试过时是这样)。有点奇怪的
foldl
包提供了一个很好的框架,可以有效地执行各种类似的操作。对于这个简单的例子,另一个选项是
foldl'
函数,第三个选项是高阶折叠:
bounds xs=foldr go stop xs minBound maxBound where…
100/foldMap 1.411 μs
100/minMax 517.6 ns

1000/foldMap 28.94 μs
1000/minMax 5.078 μs

10000/foldMap 488.4 μs
10000/minMax 51.56 μs

100000/foldMap 21.08 ms
100000/minMax 537.3 μs

1000000/foldMap 268.9 ms
1000000/minMax 8.989 ms