开发者

Computational cost of applicative style

开发者 https://www.devze.com 2023-02-15 06:29 出处:网络
I am using a small database pool in my web app. And this particular function: withPool pool = bracket (takeConn pool) (putConn pool)

I am using a small database pool in my web app. And this particular function:

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

can be rewritten in applicative style:

withPool = bracket <$> takeConn <*> putConn

Arguably it is just as readable and much more elegant. So naturally, I want to write it like that. But database connection po开发者_如何学JAVAol supposed to be fast, and I am afraid that this style introduces unnecessary overhead.

So my question is, how much overhead (if any) does use of applicative functors incur in Haskell? Are there any benchmarks?


I really suspect they'll be compiled down to the same thing in most cases. I did a tiny test,

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

but I am constraining the type of test2 there to only functions (which isn't its most generalised type, right..?)

Then I compiled with ghc -O -ddump-simpl to get some sort of intermediate output from GHC (I tried the C output, it was too ugly) and the two came out looking exactly the same, except for names.

(I also tried without -O though, and they weren't the same, nor if I leave out the type annotations)


If you're worried about that level of micro-optimisation, you should be hand-rolling assembly.

Write clear and elegant code first and foremost. If speed is an issue, do some profiling and optimise the hot-spots.

Given how simple the definition of Monad ((->) r) is, you really should trust GHC to inline the definitions for you, at which point the two versions become identical up to alpha-renaming.

0

精彩评论

暂无评论...
验证码 换一张
取 消