To learn Haskell, I've been going at this challenge, which is to check a list of phone numbers to ensure that no number is a prefix of another. However, my code is way too slow. I am really new to Haskell so I don't know what to look for in performance optimization.
I have generated a sample input which takes 5s (uncompiled via runhaskell) on my machine. What can I do to speed this up?
main = do
content <- getContents
let
allLines = lines content
caseCount = read (head allLines) :: Int
cases = tail allLines
putStr $ unlines $ map toYesNo (processCases cases caseCount)
toYesNo b
| b = "YES"
| otherwise = "NO"
processCases :: [[Char]] -> Int -> [Bool]
processCases [] num = []
processCases cases 0 = []
processCases cases remaining =
let
caseLines = read (head cases) :: Int
current = take caseLines (tail cases)
in (if (checkListConsistency current) then True else False)
: (processCases (drop (caseLines+1) cases) (remaining-1))
checkListConsistency :: [[Char]] -> Bool
checkListConsistency [] = True
checkListConsistency list =
let
number = head list
rest = tail list
in if checkNumberConsistency number rest
then checkListConsistency rest
else False
checkNumberConsistency :: [Char] -> [[Char]] -> Bool
checkNumberConsistency number [] = True
checkNumberConsistency number list =
foldr (&&) True (map (checkNumberConsistencyVsNumber number) list)
checkNumberConsistencyVsNumber :: [Char] -> [Char] -> Bool
checkNumberConsistencyVsNumber number number2 =
let
numberLength = length number
number2Length = length number2
in if numberLength > number2Length
then notStartsWith number number2
else notStartsWith number2 number
notStartsWith _ [] = False
notStartsWith [] _ = True
notStartsWith (hl:tl) (hs:ts)
| hl == hs = notStartsWith tl ts
| otherwise = True
YES
and then freezes waiting for input, is that the correct behaviour? \$\endgroup\$runhaskell phonelist.hs < file
\$\endgroup\$runhaskell
will interpret the programme (very slow) running it after compiling is instanteneous (< 0.1 seconds) \$\endgroup\$