Consider the following imperative code which finds the largest palindrome among products of 3-digit numbers (yes, it's the one of the first tasks from "Project of [outstanding mathematician of 18th century]" site):
curmax = 0
for i in range(999,100):
for j in range(999,100):
if ((i*j) < curmax): break
if (pal(i*j)):
curmax = i*j
break
print curmax
As I'm learning Haskell currently, my question is, how do you translate this (and basically any imperative construct that contains something more complex than just plain iteration, e.g. breaks, continues, temporary variables and all this) to Haskell?
My version is
maxpal i curmax
| i < 100 = curmax
| otherwise = maxpal (i-1) (innerloop 999)
where
innerloop j
| (j < 100) || (p < curmax) = curmax
| pal p = p
| otherwise = innerloop (j-1)
where p = i*j
main = print $ maxpal 999 0
but this looks like we're still in imperative uglytown.
So what could you advise, what are the approaches of dealing with such cases FP-style?
Similar answer to Daniel's and sepp2k's:
Lazy functional programming lets you write programs in a much more modular way than you see in imperative control flow like the one in your question. For instance, form the list of factors 999...100, then all products, then filter to retain only the palindromes, and then compute the maximum. Thanks to laziness, these intermediate lists will come into being only as needed and will be incrementally recycled.
For more explanation and examples, see John Hughes's classic paper Why Functional Programming Matters.
maxpal :: Int
maxpal = maximum [i*j | i <- factors, j <- factors, pal (i*j) ]
factors :: [Int]
factors = [999,998..100]
pal :: Show a => a -> Bool
pal = palL . show
palL :: (Eq a) => [a] -> Bool
palL xs = xs == reverse xs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With