2015-05-07 12 views
6

Ich lief in Haskell in eine Endlosschleife Problem und kann nicht verstehen, was die Ursache ist. Ich habe drei Versionen des gleichen Codes unten. Die erste verursacht eine Endlosschleife, während die letzteren nicht. Dies ist ein grundlegender künstlicher Code, um ein Array rekursiv zu erzeugen. In diesem Fall hat es nur drei Elemente und der einzige rekursive Aufruf ist für das dritte Element, das das größere der ersten beiden auswählt. Die if a > b-Anweisung scheint eine Schleife zu verursachen (aber später zeige ich, dass sie nicht die Ursache sein kann).Seltsame <<loop>> Ausnahme in Array-Generation

import Data.Array 

main :: IO() 
main = print grid 
    where grid = array (0, 2) $ map func [0 .. 2] 
     func i 
      | i == 2 = let a = grid ! (i - 1) 
          b = grid ! (i - 2) 
         in if a > b 
           then (i, a) 
           else (i, b) 
      | otherwise = (i, 0) 

In der folgenden Version, habe ich einfach max a b anstelle der if Anweisung verwenden. Keine Schleife hier.

main :: IO() 
main = print grid 
    where grid = array (0, 2) $ map func [0 .. 2] 
     func i 
      | i == 2 = let a = grid ! (i - 1) 
          b = grid ! (i - 2) 
         in (i, max a b) 
      | otherwise = (i, 0) 

In der folgenden Version, halte ich die if aber zip die Indizes statt eines Tupels von func zurück. Dieser läuft auch gut.

main :: IO() 
main = print grid 
    where grid = array (0, 2) $ zip [0 .. 2] $ map func [0 .. 2] 
     func i 
      | i == 2 = let a = grid ! (i - 1) 
          b = grid ! (i - 2) 
         in if a > b 
           then a 
           else b 
      | otherwise = 0 

Diese beiden anderen Fällen scheinen zu zeigen, dass es kein Problem mit der rekursiven Definition oder die Verwendung der if Aussage.

Was bleibt als Ursache der Schleife übrig? Hier

+0

Die Aussage dieser Frage ist übrigens absolut perfekt: gerade genug Code, um das Problem zu beobachten, plus einige Beobachtungen, die auf ihrem Gesicht sind völlig widersprüchlich. Plus eine klare Übersicht über das, was Sie dachten, könnte das Problem und Beweise dafür sein, dass es nicht war. Nur ein schönes Puzzle rundherum. –

Antwort

6

ist eine interessante Beobachtung: in (i, max a b), wir wissen (vor entweder a oder b Computing), dass dieses Tupel i in seiner ersten Komponente hat. Ähnlich können wir in Ihrem zip Code feststellen, dass die ersten Teile der Tupel 0, 1 und 2 sind, ohne die zweiten Teile der Tupel zu berechnen. Doch in if a > b then (i, a) else (i, b) ist es nicht offensichtlich, dass wir ein Tupel mit i im ersten Teil haben: wenn a > b Boden ist, zum Beispiel, dann ist das Ergebnis dieses Ausdrucks Boden, kein Tupel mit i im ersten Teil!

Dies ist wichtig, weil a > b Computer Computer erfordert a, die erkennende erfordert, welcher Wert in der Position 0 in dem Array, das anzeigt, ob i erfordert Wissen ist 0 in dem letzten Element der abgebildeten Liste (und daher sollte die vorhergehende 0 Wert überschrieben) -- eine Schleife.

Eine Lösung besteht darin, den (i, _) Teil aus dem if zu entfernen und (i, if a > b then a else b) zu verwenden. Dies ist im Wesentlichen was Ihre max Lösung tut.

Verwandte Themen