2

问题是我不知道如何创建类型的行为Behavior t GameState

我有更多的代码,但我只是想展示我认为有必要谈论这个问题的内容。让我知道是否有空白要填写。这就是我所拥有的:

data GameState = GameState {agent    :: Agent
                           ,universe :: Universe
                           }

type Universe = Gr Planet ()

data Command = Move PlanetName
             | Look
             | Quit
                 deriving Show

data PlayerCommand = PlayerCommand Command PID
                   | Null
                       deriving Show

updateGS :: PlayerCommand -> GameState -> GameState
updateGS (PlayerCommand (Move planet) pid) gs =
   let agent = getAgent pid gs
       nodes = labNodes $ universe gs
       current = location agent
       Just fromP = lookup (fromEnum current) nodes
       Just toP   = lookup (fromEnum planet) nodes
       fromNode = fromEnum current
       toNode = fromEnum planet
       uPlayer = Player pid (getPlanetName toP) (Location planet)
       mData = MoveData uPlayer (toNode,toP) (fromNode,fromP) nodes
       uPlanets = updateLNodeList mData
   in GameState uPlayer (mkGraph uPlanets $ labUEdges gates

initialGS :: GameState
initialGS = GameState initPlayer (makeUniverse makePlanetNodes)

和活动网络

makeNetworkDescription :: AddHandler PlayerCommand -> IO EventNetwork
makeNetworkDescription addCommandEvent = compile $ do
   eInput <- fromAddHandler addCommandEvent
   let bCommand = stepper Null eInput
   eCommandChanged <- changes bCommand
   let bGameState :: Behavior t GameState
       bGameState = stepper initialGS 
   reactimate $ (\n -> appendFile "output.txt" ("Command is " ++ show n)) <$> eCommandChanged

我相信 bGameState 需要使用 eCommandChange,但我遇到了类型问题

stepper :: a -> Event t a -> Behavior t a

这让我相信我需要转换eInput :: Event t PlayerCommand成 a eGameState :: Event t GameState,我可以用它stepper来制作Behavior t GameState

所以,我的问题是,我的思路正确吗?如果没有,我可以重新定向吗?如果是这样,eGameState :: Event t GameState会是什么样子?

针对下面的回复。当我accumB最初考虑时,我看到了一个类型错误。当我尝试你的建议时发生了什么。

let bGameState :: Behavior t GameState
    bGameState = accumB initialGS $ updateGS <$ eInput

产生错误

 Couldn't match expected type `GameState'
             with actual type `PlayerCommand'
 Expected type: GameState -> GameState
   Actual type: PlayerCommand -> GameState -> GameState
 In the first argument of `(<$)', namely `updateGS'
 In the second argument of `($)', namely `updateGS <$ eInput'

不知道该怎么做。我会看看你的例子,看看答案是否清楚。感谢您指出accumB是正确的方法,因为我专注于stepper

我越研究建议的代码,我就越对类型错误感到困惑。

4

1 回答 1

2

实际上,您需要创建一个事件来记住 aGameState并将updateGS函数应用于它以创建一个新事件。这就是函数accumE及其表亲的目的accumB。特别是,你可以写

bGameState = accumB initialGS $ updateGS <$> eInput

要了解有关此模式的更多信息,请查看示例页面上的示例,特别是 Counter.hs 和 TwoCounters.hs 示例。


值得一提的另一点是我建议避免使用该changes功能,除非您正在处理低级框​​架的东西。如文档中所述,它有几个限制;最讨厌的限制是在执行之前该值不可用reactimate。这样你就可以很容易地创建一个无限循环,它的目的真的很窄。

在您的情况下,bCommand无论如何,似乎都是多余的,您有eCommandChanged = eInput.

士气:将事件转化为行为很容易,但没有回头路。

于 2012-10-24T13:54:05.730 回答