solrize
в #haskell задал вопрос об одной версии этого кода, и я попробовал некоторые другие случаи и задавался вопросом, что происходит. На моей машине "быстрый" код занимает ~ 1 секунду, а "медленный" код занимает ~ 1.3-1.5 (все скомпилировано с помощью 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]
Я надеялся, что GHC сможет превратить logBase x y
точно так же, как log y / log x
, когда будет специализировано. Что здесь происходит, и какой будет рекомендуемый способ использования logBase
?