Haskell 哈斯克尔:我想我真的可以在这里像使用Lisp一样使用宏

Haskell 哈斯克尔:我想我真的可以在这里像使用Lisp一样使用宏,haskell,template-haskell,Haskell,Template Haskell,我的小型足球游戏的AI代码基本上是这样工作的:有一个函数可以导出描述球场当前状况的事实: deriveFacts :: GameState -> [Fact] 。。。事实是这样的: data Fact = FactCanIntercept ObjId ObjId | FactBestPosition Team Spot Spot | FactKickOff | FactBallCarrier ObjId | FactBestShootingVector Veloc

我的小型足球游戏的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)]
。。。有些规则看起来都是这样的:

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)]
rule\u shot facts=do

factballcharrier您可以将大多数事实数据重构为记录对象

data FactRec = FR {
   canIntercept :: [(ObjId,ObjId)], -- use lists for things you previously had multiple times
   factBestPosition :: [(Team,Spot,Spot)], -- not sure about this one, maybe two entries not one list 
   kickOff :: Bool,
   ballCarrier :: ObjID,
   factBestShootingVector :: Velocity3, 
   factBestPassingVector :: Velocity3,
   .....
   }
这将为您提供访问器函数中的bulti

if kickOff fr then something else somethingelse
因此,您不需要编写所有的检查函数,而是需要编写

rule_shoot facts = message (ballCarrier facts, shoot $ goalVector facts)

如果有一些事实确实可能存在,也可能不存在,它们可能是某种类型的,可能是什么,如果有一些事实可以存在任意次数,它们可以是列表。

谢谢,这给了我一些思考的东西!为什么首先要使用事实列表。。。当时感觉有点对,但我真的不知道为什么…OP的原始代码
rule\u shot
使用了
Maybe
monad,
listToMaybe
将最多返回列表的第一个元素,因此,也许应该使用
Maybe
类型来定义
FR
记录,而不是列表和
Bool
。这完全取决于你希望
rule\u shot
的行为方式。@user5402通常不会-我认为
可能
的内容主要是为了处理列表中可能不包含你要查找的数据这一事实。无论如何,当我说“如果有真实可能存在或不存在的事实,它们可能是某种类型的,可能是某种东西,如果有任意次数的事实,它们可以是列表”时,我已经讨论了这种可能性及其普遍性