10

我在我的网络应用程序中使用了一个小型数据库池。而这个特殊的功能:

withPool pool = bracket (takeConn pool) (putConn pool)

可以用应用风格重写:

withPool = bracket <$> takeConn <*> putConn

可以说它同样具有可读性并且更加优雅。所以很自然,我想这样写。但是数据库连接池应该很快,恐怕这种风格会引入不必要的开销。

所以我的问题是,在 Haskell 中使用应用函子会产生多少开销(如果有的话)?有没有基准?

4

2 回答 2

19

我真的怀疑在大多数情况下它们会被编译成相同的东西。我做了一个小测试,

import Control.Applicative

test1 :: (b -> b -> c) -> (a -> b) -> (a -> b) -> a -> c
test1 bracket takeConn putConn pool = bracket (takeConn pool) (putConn pool)

test2 :: (b -> b -> c) -> (a -> b) -> (a -> b) -> a -> c
test2 bracket takeConn putConn = bracket <$> takeConn <*> putConn

但我将 test2 的类型限制为只有函数(这不是它最通用的类​​型,对吧..?)

然后我编译以ghc -O -ddump-simpl从 GHC 获得某种中间输出(我尝试了 C 输出,它太丑了),两者看起来完全一样,除了名称。

(虽然我也尝试过不使用 -O ,但它们不一样,也没有省略类型注释)

于 2011-03-08T09:22:26.937 回答
12

如果您担心那种级别的微优化,您应该手动滚动组装。

首先编写清晰优雅的代码。如果速度是一个问题,请进行一些分析并优化热点。

鉴于 Monad ((->) r) 的定义非常简单,您真的应该相信 GHC 会为您内联定义,此时两个版本在 alpha 重命名之前变得相同。

于 2011-03-08T15:38:15.850 回答