2016-02-14 68 views
1

我在Haskell写一个程序在d &两个玩家之间进行模拟作战D.我使用的方法是存储玩家地图,然后有采取“攻击”功能一个玩家,并根据是否连接的攻击返回一个具有更新的健康状况的IO Player。我的所有代码似乎都按预期工作,直到最后一个函数combatcombat应该采取两种球员,有第一个攻击第二,检查第二个是死的,如果没有,复发与逆转玩家的顺序。相反,它似乎无限循环。Haskell中无限循环做阻断

函数本身是如下 -

combat :: Player -> Player -> IO String 
combat a b = do 
    damaged <- a `attacks` b 
    nextRound <- combat damaged a 
    return $ if (victor a damaged) /= "No victor yet" then (victor a damaged) else nextRound 

attacks函数有两个玩家,检查第一个的ID,并适用的到第二个攻击的适当序列。当我在GHCi中使用它时,它工作得很好,所以我认为那里没有问题。

victor函数需要两名玩家,检查它们中的任何一个是否死亡(定义为HP < = 0),并返回描述结果的字符串。当我写的combat玩具版本,而不只是返回“测试”时未满足的条件任何递归,它返回的组合“玩家1胜!”和“测试”,所以我认为那里没有问题。

我遇到了类似的问题,让绑定,其中有人遇到了无限循环时,他们有像let n = n + 1代码,但我不知道如果<-工作在相同的方式(或者,如果它,我还能怎么写呢)。

+0

这段代码永远不会到达'return'行。每次你打电话给'战斗'时,它都会以自相反的方式调用自己的观点,但从来没有完成过,因为在有机会超越那条线之前,它会自我调用。 –

+0

@PeterHall好吧,这很有道理。但是,当我在'else'语句中将''''''''''''''''''''''''''打乱了一个类型错误时(它需要一个普通的字符串,但它得到一个IO字符串),这是我在上面递归时试图解决的问题if语句。 – Kumarbis

回答

2

正如评论中所提到的,您需要在执行递归步骤之前执行终止检查,否则您将永远无法终止。这里有一个小的重新排序:

combat :: Player -> Player -> IO String 
combat a b = do 
    damaged <- a `attacks` b 
    case victor a damaged of 
     "No victor yet" -> combat damaged a 
     winner -> return winner 

注意,这将是好得多,如果victor返回Maybe String代替,这样你就不会依赖于这个神奇的字符串"No victor yet"。然后你可以这样写:

combat :: Player -> Player -> IO String 
combat a b = do 
    damaged <- a `attacks` b 
    case victor a damaged of 
     Nothing -> combat damaged a 
     Just winner -> return winner 
1

请尽量将来发布的最低编译能够例子。

正如评论中所述,无条件地致电combatcombat正文内是非首发。相反,将其沉入if-then-else的适当臂部。

您也提到的情况下,一个放置combat当你有一个类型的错误。我猜你使用return $ if ...这意味着要么分公司将被包裹在IO ...另一层但你combatIO _类型的了。

combat :: Player -> Player -> IO String 
combat a b = do 
    damaged <- a `attacks` b 
    if (victor a damaged) /= "No victor yet" 
     then return (victor a damaged) 
     else combat damaged a 

现在还有两个其他的疣。一个是重复的声明,称为victor。另一个是使用字符串比较来确定程序流程,呃!相反,你如何使victor返回一个ADT?

data Status = Dead String | Alive 

combat :: Player -> Player -> IO String 
combat a b = do 
    damaged <- a `attacks` b 
    case victor a damaged of 
     Alive -> combat damaged a 
     Dead s -> return s