我在我的网络应用中使用了一个小型数据库池。而这个特殊功能:
withPool pool = bracket (takeConn pool) (putConn pool)
可以用应用风格重写:
withPool = bracket <$> takeConn <*> putConn
可以说它具有可读性和优雅性。很自然地,我想这样写。但是数据库连接池应该很快,我担心这种风格会带来不必要的开销。
所以我的问题是,在Haskell中使用应用函子有多少开销(如果有的话)?有基准吗?
答案 0 :(得分: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,但它们不一样,我也省略了类型注释)
答案 1 :(得分:12)
如果你担心这种微观优化水平,你应该手动组装。
首先写出清晰优雅的代码。如果速度是一个问题,请进行一些分析并优化热点。
鉴于Monad(( - &gt;)r)的定义有多简单,你真的应该相信GHC为你定义内容,此时两个版本在alpha重命名后变得相同。