我的小足球比赛的 AI 代码基本上是这样工作的:有一个函数可以得出描述球场当前情况的事实:
deriveFacts :: GameState -> [Fact]
...事实看起来像这样:
data Fact =
FactCanIntercept ObjId ObjId
| FactBestPosition Team Spot Spot
| FactKickOff
| FactBallCarrier ObjId
| FactBestShootingVector Velocity3
| FactBestPassingVector Velocity3
| ...
...并且有些规则看起来像这样:
rule_shoot facts = do
FactBallCarrier ballCarrier <- checkBallCarrier facts
FactBestShootingVector goalVector <- checkBestShootingVector facts
return [message (ballCarrier, shoot goalVector)]
然后有一个规则引擎运行所有规则并收集结果消息。
到目前为止还不错,而且效果很好。不过,有什么烦人的:在这种方法中,我需要一个像这样的“访问器”函数来处理每个事实:
checkBestShootingVector :: [Fact] -> Maybe Fact
checkBestShootingVector facts =
listToMaybe [e | e@(FactBestShootingVector {}) <- facts]
这种方法会导致很多丑陋的样板代码。我的问题:是否有一个优雅的解决方案可以消除手动创建这些访问器函数的需要?