Which method is faster in Haskell to determine whether an integer is within a closed area, > = & & < =, or elem?
suppose I have an integer x , and I want to judge whether the integer is in the interval [1, limit] . In Haskell, I can think of two schemes:
-
x > = 1 and x < = limit
-
elem x [1..limit]
I used the Profiling, code of GCI as follows:
I wonder if the method is correct, but which of the two schemes is faster?
I didn't expect SF to have Haskell problems:)
in fact, if you look at the results of Profiling, inherited% time
and inherited% alloc
of in_range
are larger than larger_than
, accounting for 100% and 93.3% of the entire program execution. So the first way is fast.
Writing a rewrite rule may optimize elem
and enumFromTo
.
I tried to write rewrite rule, and found that inline, in enumFromTo caused rewrite rule not to take effect, so first implement a myEnumFromTo
to see the effect:
module Main where
{--sharp RULES
"elem/myEnumFromTo" forall (x::Integer) (n::Integer) (m::Integer) . elem x (myEnumFromTo n m) = x >= n && x <= m
-sharp-}
{--sharp NOINLINE myEnumFromTo -sharp-}
myEnumFromTo n m
| n == m = [n]
| otherwise = [n] PP myEnumFromTo (n + 1) m
main = do
print $ {--sharp SCC larger_than -sharp-} lth 100000000
print $ {--sharp scc in_range -sharp-} inr 100000000
lth :: Integer -> Bool
lth x = (x >= 1 && x <= 65535000000000)
inr :: Integer -> Bool
inr x = let m = 65535000000000::Integer in
x `elem` (myEnumFromTo 1 m)
the Profile result is as follows:
main Main app/Main.hs:(12,1)-(14,48) 0.0 15.8
individual inherited
COST CENTRE MODULE SRC no. entries %time %alloc %time %alloc
MAIN MAIN <built-in> 144 0 0.0 29.6 0.0 100.0
CAF GHC.Conc.Signal <entire-module> 252 0 0.0 0.9 0.0 0.9
CAF GHC.IO.Encoding <entire-module> 241 0 0.0 3.8 0.0 3.8
CAF GHC.IO.Encoding.Iconv <entire-module> 239 0 0.0 0.3 0.0 0.3
CAF GHC.IO.Handle.FD <entire-module> 231 0 0.0 47.3 0.0 47.3
CAF GHC.IO.Handle.Text <entire-module> 229 0 0.0 0.1 0.0 0.1
CAF GHC.Show <entire-module> 214 0 0.0 0.4 0.0 0.4
CAF GHC.Event.Thread <entire-module> 193 0 0.0 1.7 0.0 1.7
CAF GHC.Event.Poll <entire-module> 160 0 0.0 0.1 0.0 0.1
CAF:main1 Main <no location info> 286 0 0.0 0.0 0.0 0.0
main Main app/Main.hs:(12,1)-(14,48) 288 1 0.0 0.0 0.0 0.0
CAF:main2 Main <no location info> 284 0 0.0 0.0 0.0 0.0
main Main app/Main.hs:(12,1)-(14,48) 293 0 0.0 0.0 0.0 0.0
in_range Main app/Main.hs:14:32-48 294 1 0.0 0.0 0.0 0.0
inr Main app/Main.hs:(20,1)-(21,29) 295 1 0.0 0.0 0.0 0.0
inr.m Main app/Main.hs:20:13-39 296 1 0.0 0.0 0.0 0.0
CAF:main4 Main <no location info> 285 0 0.0 0.0 0.0 0.0
main Main app/Main.hs:(12,1)-(14,48) 290 0 0.0 0.0 0.0 0.0
larger_than Main app/Main.hs:13:36-48 291 1 0.0 0.0 0.0 0.0
lth Main app/Main.hs:17:1-39 292 1 0.0 0.0 0.0 0.0
main Main app/Main.hs:(12,1)-(14,48) 289 0 0.0 15.8 0.0 15.8
I don't know how to make it effective for enumFromTo
: (