首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell Prelude.head错误,空列表

Haskell Prelude.head错误,空列表
EN

Stack Overflow用户
提问于 2013-03-08 02:00:35
回答 1查看 1.5K关注 0票数 2

我的代码正在抛出一个空列表错误。当我跑步时:

代码语言:javascript
复制
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)]

这种复制的主要功能应该是根据父母的“健康度”是否超过某一水平来生成一个新的代理,然后在代理列表中除该代理之外的所有代理运行相同的功能。

它的产出如下:

代码语言:javascript
复制
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

当我调用reproduce时,它会抛出prelude.head空列表错误,而胜利者、代理和int列表都是非空的,因此在递归的最后一次迭代中它可能是一个边缘大小写错误。为什么会发生这种情况?

EN

回答 1

Stack Overflow用户

发布于 2013-03-08 08:53:44

解决方案相对简单:简单地说,在Haskell程序中不使用headtail。(虽然在一些情况下,这样做是合理的,但最好在一开始就假设没有。)

相反,使用模式匹配。通常,您总是希望对空列表和非空列表进行正确的模式匹配,如下所示:

代码语言:javascript
复制
fun :: [Something] -> ...
fun []       = ...
fun (x : xs) = ... -- x is head, xs is tail

这样,您就不得不处理错误,并且您知道引用xxs不能再失败了,因为列表已经被确定为非空的。

如果您的程序中有许多不应该为空的列表,那么您必须手动跟踪这些条件(至少应该记录它们)。但即便如此,在这样的let-binding中进行模式匹配也更好

代码语言:javascript
复制
(winner : _) = ...

然后,稍后将winner作为该列表的标题,因为您将得到一条涉及模式匹配失败的行号的错误消息。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15285439

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档