I copied the Euler.11 solution given on
( http://www.haskell.org/haskellwiki/Euler_problems/11_to_20#Problem_11), but it fails with an indexing error: ” (Array.!): undefined array element“.
Of course firstly I’d like a better error message(!), perhaps even giving the failed index, but failing that I tried to debug it.
The data is input correctly, and a print of it shows the right bounds, and data.
So I added a few trace messages, to both the result expression, and the body of the comprehension. I get lots of trace results from the final expression, but none from the body computations. Why?
prods :: Array (Int, Int) Int -> [Int]
-- trace ("xs: " ++ show xs) (product xs)
prods a = [trace ("xs: " ++ show xs) (product xs) | i <- range $ bounds a,
s <- senses,
let trace1 = check "i: " i,
let is = take 4 $ iterate s i,
let trace2 = check "is: " is,
all (inArray a) is,
let xs = map (a!) is]
-- Doit
-- euler = print . maximum . prods . input =<< getContents
euler eData = maximum . prods $ input eData
-- Debugging tracecheck :: String -> a -> a
check msg v | trace (msg ++ (show v)) True = v
First, making the error message include the failing index would require the
Showconstraint to be added to the array indices, which may be undesired.Second, as Roman said, the messages are not printed because of lazy evaluation. Bang-patterns (
let !trace = check "i: " i) may be the most convenient way to circumvent it, but I don’t know exactly how those work inside of list comprehensions.Next, the
undefined array elementmessage tells you that the array was constructed incorrectly (some elements were left undefined), so you need to debug the function constructing it rather than the function using it.