solrize in #haskell asked a question about one version of this code and I tried some other cases and was wondering what was going on. On my machine the "fast" code takes ~1 second and the "slow" code takes ~1.3-1.5 (everything is compiled with ghc -O2).

import Data.List

log10 :: Double -> Double
--log10 x = log x / log 10 -- fast
--log10 = logBase 10 -- slow
--log10 = barLogBase 10 -- fast
--log10 = bazLogBase 10 -- fast
log10 = fooLogBase 10 -- see below

class Foo a where
    fooLogBase :: a -> a -> a

instance Foo Double where
    --fooLogBase x y = log y / log x -- slow
    fooLogBase x = let lx = log x in \y -> log y / lx -- fast


barLogBase :: Double -> Double -> Double
barLogBase x y = log y / log x

bazLogBase :: Double -> Double -> Double
bazLogBase x = let lx = log x in \y -> log y / lx


main :: IO ()
main = print . foldl' (+) 0 . map log10 $ [1..1e7]

I'd've hoped that GHC would be able to turn logBase x y into exactly the same thing as log y / log x, when specialised. What's going on here, and what would be the recommended way of using logBase?

Edit
Report