2011-09-11 8 views
0

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 

答えて

2

まず、障害の指標は望ましくないかもしれ配列インデックスに追加するShow制約を必要とするであろうが挙げられます。

第2に、ローマン氏によると、怠惰な評価のためにメッセージは印刷されません。 Bang-patterns(let !trace = check "i: " i)は、それを回避する最も便利な方法かもしれませんが、リスト内包表記の中でそれらがどのように機能するかは正確にはわかりません。

次に、undefined array elementメッセージは、配列が正しく構成されていない(いくつかの要素が未定義のまま残っている)ことを伝えるため、関数を使用する関数ではなくデバッグする必要があります。

+0

多くのありがとうございます。明らかです(今!)。私はそれを構築した後に配列を印刷しました、そして、それはすべて期待どおりの境界で見えました。私は、それがいくつかの未定義の値を持っているかどうか/それをもう少し見るためにもう少し試してみるでしょう。 – guthrie

+0

データの設定が間違っているのは正しいですか?私はエラーメッセージを誤解していました。 – guthrie

5

ハスケルは遅延言語(*)です。 trace1およびtrace2を計算に使用しないため、評価されず、何も印刷されません。

あなたは

let is = take 4 $ iterate s trace1 

let is = take 4 $ iterate s i 

を交換する場合たとえば、その後、trace1が使用され、メッセージをトレースにつながるはず。

(*)より正確には、GHC、最も今日使用Haskellの実装は、Haskellの非厳格なセマンティクスを達成するために遅延評価を使用しています。これが理にかなっていないかどうか気にしないでください。エラーメッセージを作成