Haskell 调试列表理解

Haskell 调试列表理解,haskell,list-comprehension,lazy-evaluation,Haskell,List Comprehension,Lazy Evaluation,我复制了上给出的Euler.11解 (),但由于索引错误而失败:“(数组.!):未定义的数组元素”。 当然,首先我想要一个更好的错误消息(!),甚至可能给出失败的索引,但如果失败,我尝试调试它 数据输入正确,打印出来显示正确的边界和数据 所以我在结果表达式和理解主体中添加了一些跟踪消息。我从最终的表达式中得到了很多跟踪结果,但没有从主体计算中得到。为什么? prods :: Array (Int, Int) Int -> [Int] -- trace ("xs: " ++ show xs)

我复制了上给出的Euler.11解 (),但由于索引错误而失败:“(数组.!):未定义的数组元素”。 当然,首先我想要一个更好的错误消息(!),甚至可能给出失败的索引,但如果失败,我尝试调试它

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

所以我在结果表达式和理解主体中添加了一些跟踪消息。我从最终的表达式中得到了很多跟踪结果,但没有从主体计算中得到。为什么?

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
prods::数组(Int,Int)Int->[Int]
--跟踪(“xs:++显示xs)(产品xs)
prods a=[trace(“xs:++show xs)(product xs)| iHaskell是一种惰性语言(*)。在计算中不使用
trace1
trace2
,因此不会对它们进行计算,也不会打印任何内容

例如,如果替换

let is = take 4 $ iterate s i

然后将使用
trace1
,并将导致跟踪消息


(*)更准确地说,GHC是目前使用最多的Haskell实现,它使用延迟求值来实现Haskell的非严格语义。不管这是否有意义。

首先,使错误消息包括失败的索引需要将
Show
约束添加到数组索引中,这可能是不希望的

第二,正如Roman所说,这些消息之所以没有打印出来,是因为计算太慢。Bang模式(
let!trace=check“i:”i
)可能是绕过它的最方便的方法,但我不知道它们在列表理解中是如何工作的


接下来,
undefined array element
消息告诉您数组构造不正确(有些元素未定义),因此您需要调试构造它的函数,而不是使用它的函数。

非常感谢所有要点;看起来很明显(现在!)。我确实在构建数组后打印了它,它看起来都很好,具有预期的边界。我将进一步使用它,看看它是否/如何获得一些未定义的值。关于数据的错误设置,您是对的-我误解了错误消息。
let is = take 4 $ iterate s trace1