2014-05-07 43 views
0
test :: [Int] -> [Int] 
test l | (length l) > 5 = l 
     | otherwise = test l ++ take 1 searchSpace 
    where searchSpace = zipWith (*) [100..999] [100..999] 

上面的代碼爲我提供了堆棧溢出。我假設Haskell在searchSpace中完全評估並存儲zipWith的結果。如果我只想讓我的程序逐步應用take 1,那麼創建此列表的方式會是什麼?乘以兩個列表導致堆棧溢出

+0

如果你想問一下關於堆棧溢出的問題,可以在元XD – aIKid

回答

1

如果l爲< = 5,表明您正在調用test l recusrively而沒有終止條件。 您更希望像

test :: [Int] -> [Int] 
test l | (length l) > 5 = l 
     | null l = take 1 searchSpace 
     | otherwise = test init_of_l ++ take 1 searchSpace 
    where searchSpace = zipWith (*) [100..999] [100..999] 
      init_of_l = init l 

working example here

+1

上做什麼'(l-1)'是什麼意思?可能'尾巴'將提供預期的行爲。 –

+0

@ J.Abrahamson感謝您指點,糾正 –

+1

@Chris爲了每次獲得不同數量的元素,您可以查看[本示例](http://codepad.org/3vPcHbSR) –

6

你有一個無限循環。如果我們通過像[1..6]的列表(選擇,使得長度大於5)test它降低這樣的:

test [1..6] 
test [1..6] ++ take 1 searchSpace 
test [1..6] ++ take 1 searchSpace ++ take 1 searchSpace 
test [1..6] ++ take 1 searchSpace ++ take 1 searchSpace ++ take 1 searchSpace 
... 

評估樹的頂部在兩個步驟必須評價其左邊的參數進行變(++)

[]  ++ ys = ys 
(x:xs) ++ ys = x : (xs ++ ys) 

所以最終結果是該函數幾乎沒有做任何工作,並且花費其所有的時間一再跳水到您的無限循環的分支。

+0

一個後續問題。我寫了這個函數作爲測試,看看searchSpace是否會讓我每次在遞歸中調用它時都會獲得一個新值(並不清楚在這種情況下where子句的處理方式)。我發現它爲每個實例重複了最初的100 * 100。對我來說,正確的方式是什麼讓價值觀保持不變? – Chris

+0

對於列表大小大於5的情況,不存在遞歸。對於小於或等於5的大小,將觀察到無限循環。不是嗎? –

+0

糟糕,誤讀了該功能。我應該使用'[1..4]'觸發錯誤。 –