Heinrich Apfelmus慷慨地附和了这个问题。我曾考虑将accumB
其用作解决方案,但认为会有类型错误。无论如何尝试了他的建议后,我确实收到了一个类型错误。
let bGameState :: Behavior t GameState
bGameState = accumB initialGS $ updateGS <$ eInput
yields the error
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'
所以我研究了(<$)
,并搞砸了部分应用程序。看了他建议的例子。我这样做的次数越多,我就越认为上面的代码应该可以工作,但我对它为什么不工作感到困惑。
这是我认为应该发生的事情:
因为(<$)
是类型(<$) :: a -> f b -> f a
并且 updateGS 是类型updateGS :: PlayerCommand -> GameState -> GameState
并且eInput
是类型Event t PlayerCommand
那么不应该updateGS <$ eInput
屈服
Event t (GameState -> GameState)
?
我的推理在某个地方有缺陷,有人可以指出哪里吗?
更新:当我尝试使用时,(<$>)
我收到以下错误
大纲.hs:158:21:
Could not deduce (t ~ t1)
from the context (Frameworks t)
bound by a type expected by the context:
Frameworks t => Moment t ()
at outline.hs:(153,42)-(159,93)
`t' is a rigid type variable bound by
a type expected by the context: Frameworks t => Moment t ()
at outline.hs:153:42
`t1' is a rigid type variable bound by
the type signature for bGameState :: Behavior t1 GameState
at outline.hs:158:8
Expected type: Behavior t1 GameState
Actual type: Behavior t GameState
In the expression: accumB initialGS $ updateGS <$> eInput
In an equation for `bGameState':
bGameState = accumB initialGS $ updateGS <$> eInput
供参考,这是整个功能
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 = accumB initialGS $ updateGS <$> eInput
reactimate $ (\n -> appendFile "output.txt" ("Command is " ++ show n)) <$>
eCommandChanged