调试列表理解

gut*_*rie 0 haskell list-comprehension lazy-evaluation

我复制了(http://www.haskell.org/haskellwiki/Euler_problems/11_to_20#Problem_11)上给出的Euler.11解决方案,但它失败并出现索引错误:" (Array.!):undefined array element ".当然首先我想要一个更好的错误消息(!),甚至可能给出失败的索引,但是我没有尝试调试它.

数据输入正确,打印数据显示正确的边界和数据.

所以我在结果表达式和理解体中添加了一些跟踪消息.我从最终表达式中获得了大量的跟踪结果,但是没有来自主体计算的结果.为什么?

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
Run Code Online (Sandbox Code Playgroud)

Rom*_*aka 5

Haskell是一种懒惰的语言(*).您不在计算中使用 trace1trace2,因此不会对它们进行评估,也不会打印任何内容.

例如,如果您替换

let is = take 4 $ iterate s i
Run Code Online (Sandbox Code Playgroud)

let is = take 4 $ iterate s trace1
Run Code Online (Sandbox Code Playgroud)

然后trace1将被使用并且应该导致跟踪消息.

(*)更确切地说,GHC(今天最常用的Haskell实现)使用惰性求值来实现Haskell的非严格语义.没关系,如果这没有意义.