I'm experimenting with Haskell profiling with a simple recursive max algorithm:
max_tag :: Integer -> [Integer] -> Integer
max_tag head [] = head
max_tag head (x:xs) =
let {m = max_tag x xs} in
let {b = (Prelude.<=) m head} in
case b of {True -> head; False -> m}
When I compare it to a python imperative equivalent, I get a 10x speed factor in favor of python:
with open("input.txt") as fl:
data = [int(d) for d in fl.read().splitlines()]
max_ = 0
for d in data:
if max_ < d:
max_ = d
print(max_)
- It seems there is an inherent limitation of using tail recursion in the
Haskellcase, am I right? - Any other way to make the Haskell code faster?
- The input file contains
1Munsigned, unbounded integers (on average 32 digits)
For completeness, here is the complete Haskell file (not sure it is needed):
import Max
import System.IO
import Control.Monad
import System.Environment
import Prelude
readInt :: String -> Integer
readInt = read
max_tag :: Integer -> [Integer] -> Integer
max_tag head [] = head
max_tag head (x:xs) =
let {m = max_tag x xs} in
let {b = (Prelude.<=) m head} in
case b of {True -> head; False -> m}
main = do
args <- getArgs
contents <- readFile "input.txt"
let numbers_as_strings = words $ contents
let numbers = map readInt numbers_as_strings
let max_number = max_tag 0 numbers
print max_number
EDIT: refactor suggested by @Willem Van Onsem, works ! (28 sec -> 12 sec)
max_bar :: Integer -> [Integer] -> Integer
max_bar head [] = head
max_bar head (x:xs) =
let {b = head < x} in
let {m = case b of {True -> x; False -> head}} in
max_bar m xs
Any ideas on further improvements? I must be faster than python !