2013-03-08 62 views
2

我的代碼拋出一個空列表錯誤。當我運行:Haskell Prelude.head錯誤,空列表

makeAgent :: Agent -> [Agent] -> Agent 
makeAgent (Agent func n _) agents = (Agent func (n++(show $ length $ sameNames n agents)) empty) --appends number to name to differentiate agents 
    where sameNames n agents = filter (findName n) agents 
      findName n1 (Agent _ n2 _) = (slice 0 3 n1) == (slice 0 3 n2) --ignore the suffix 
      empty = head $ getEmpty (positions agents) (fst $ getGrid agents) --getGrid returns a tuple, but currently assume to be a square 

baseline :: [Interaction] -> Float 
baseline int = (fromIntegral total)/len 
    where total = sum sums 
     sums = map snd (showSums int) 
     agents = nub $ map (\(Interaction a1 a2 _) -> a2) int 
     len = fromIntegral $ length agents 

reproduce :: Float -> [Interaction] -> [Agent] --so baseline isn't recalulated every time 
reproduce _ [] = [] 
reproduce base interaction = winners ++ [newAgent] ++ reproduce base (tail interaction) 
    where agents = nub $ concat $ map (\(Interaction a1 a2 _) -> a1:a2:[]) interaction 
      winners = [a | a <- agents, (sumAgent interaction a) >= (round base)] 
      newAgent = makeAgent (head winners) winners 


main = do 
    output "Length" (fromIntegral $ length int) 
    output "Baseline" base 
    output "Agents" agents 
    output "Sums" (showSums int) 
    output "winners" winners 
    output "NeAgent" (makeAgent (head winners)winners) 
    output "New Agents" (reproduce base int) 

    where agents = generate 4 
      int = playRound agents 20 
      base = baseline int 
      winners = [a | a <- agents, (sumAgent int a) >= (round base)] 

這是什麼重現,主要功能,應該做的根據自己的父母「全民健身」是否超過一定水平時產生一個新的代理,然後用所有,但有運行相同的功能代理列表中的代理。

它輸出:

Length: 16 
Baseline: 280.0 
Agents: [c_pavlov(-1,-1),c_titForTat(-1,0),c_sucker(-1,1),b_grim(0,-1)] 
Sums: [("c_pavlov",280),("c_titForTat",280),("c_sucker",280),("b_grim",280)] 
winners: [c_pavlov(-1,-1),c_titForTat(-1,0),c_sucker(-1,1),b_grim(0,-1)] 
NeAgent: c_pavlov1(0,0) 
prisoners: Prelude.head: empty list 

當我打電話重現,它拋出prelude.head空列表錯誤,獲獎者,代理人,和int列表是所有非空的,所以它可能是一個邊緣在遞歸的最後一次迭代中出現大小寫錯誤。這是爲什麼發生?

+0

您不會向我們展示打印「囚犯」的行 – Ingo 2013-03-08 09:45:57

+0

不是文件的名稱,所以這就是它在錯誤發生之前的前綴。 – MichaelFine 2013-03-08 21:37:48

+0

請提供完整的信息來源。 – 2013-03-10 16:58:18

回答

1

您並沒有完全說出錯的發生位置。大概是當你撥打tailhead而不檢查列表是否爲空。

如果是這種情況,您可以使用模式匹配修復空的interaction列表。

否則,您需要提供有關錯誤的更多信息。

(編輯:與頭替換尾部)

+0

正弦錯誤是'Prelude.head'我不得不說這不太可能 – 2013-03-08 04:24:44

+0

啊!我正在尋找原始文章中的錯誤消息,但沒有看到它。儘管如此,建議(使用模式匹配)仍然保持不變,儘管在kosmikus的回答中更充分地表達了這一點。 – 2013-03-08 12:33:29

8

的解決方案是相對比較簡單:只需不Haskell程序使用headtail。 (雖然有幾種情況這樣做是合理的,但最好在開始時假設沒有。)

而是使用模式匹配。通常情況下,你要一直都空列表和非空列表上正常模式匹配,就像這樣:

fun :: [Something] -> ... 
fun []  = ... 
fun (x : xs) = ... -- x is head, xs is tail 

這樣,你不得不處理錯誤,你知道參考xxs不能再失敗,因爲該列表已被確定爲非空。

如果您的程序中有很多列表不應該爲空,那麼您必須手動跟蹤這些條件(並且至少應該有文檔他們)。但即便如此,它在一個let - 結合更好的模式匹配這樣

(winner : _) = ... 

,然後參考winner該名單中的後頭,因爲你會得到涉及的行號,該模式的錯誤信息比賽失敗。