gpt4 book ai didi

haskell - 我自己定义严格的应用程序($!)不会产生相同的性能

转载 作者:行者123 更新时间:2023-12-02 07:21:19 25 4
gpt4 key购买 nike

我正在阅读this blog post by Michael Snoyman最近。在那里建议的练习中,我尝试自己定义 $! 运算符:

import Prelude hiding ( ($!) )

($!) :: (a -> b) -> a -> b
($!) f x = x `seq` f x

mysum :: [Int] -> Int
mysum list0 =
go list0 0
where
go [] total = total
go (x:xs) total = go xs $! total + x

main = print $ mysum [1..1000000]

我认为这很有效,尽管内存的使用很糟糕。我的第一个问题是这样的。为什么效果不佳?

然后,我在Prelude中检查了它的定义。内容如下:

($!)                    :: (a -> b) -> a -> b
f $! x = let !vx = x in f vx -- see #2273

所以,我将其复制到我的代码中:

{-# LANGUAGE BangPatterns #-}

import Prelude hiding ( ($!) )

($!) :: (a -> b) -> a -> b
($!) f x =
let !vx = x
in f vx

mysum :: [Int] -> Int
mysum list0 =
go list0 0
where
go [] total = total
go (x:xs) total = go xs $! total + x

main = print $ mysum [1..1000000]

结果是:

Linking mysum4 ...
500000500000
209,344,064 bytes allocated in the heap
130,602,696 bytes copied during GC
54,339,936 bytes maximum residency (8 sample(s))
66,624 bytes maximum slop
80 MB total memory in use (0 MB lost due to fragmentation)

您可以看到,与使用 Prelude 的 $! 运算符的结果相比,这是多么糟糕:

Linking mysum4 ...
500000500000
152,051,776 bytes allocated in the heap
41,752 bytes copied during GC
44,384 bytes maximum residency (2 sample(s))
21,152 bytes maximum slop
1 MB total memory in use (0 MB lost due to fragmentation)

我的第二个问题是这种差异从何而来?

此外,我认为可以这样重写:

($!) :: (a -> b) -> a -> b
f $! !x = f x

有什么理由不这样做吗?这是我的第三个问题。

最佳答案

啊哈!这是一个优先级问题。您忘记粘贴该行:

infixr 0  $!

因此,当您使用自己的版本时,它会被解析为

go (x:xs) total = (go xs $! total) + x

这显然具有糟糕的性能。它甚至给了你正确的答案,这几乎是巧合。

关于haskell - 我自己定义严格的应用程序($!)不会产生相同的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49839049/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com