2012-10-25 78 views
4

Heinrich Apfelmus慷慨地插入this问题。我曾考虑使用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)

我的推理在某处存在缺陷,有人可以指出哪里?

更新:当我尝试使用(<$>)我收到以下错误

outline.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 
+0

第二个问题与第一个无关。尝试从'bGameState'中删除类型签名 - 它太多态了('t'上有一个隐含的'forall')。 – hammar

+0

再次感谢哈马尔。 –

回答

5

代码有什么问题

您应该使用<$>而不是<$

  • <$>,又名fmap适用于右手侧事件的价值,一个函数,它是你想在这种情况下该怎么做。
  • <$替换右侧事件的值与左手边,给你一个事件发生在同一时间的原始,但总是包含相同的值。

    注:x <$ econst x <$> e相同。

为什么你的推理是错误

我们正在努力,以确定该类型subterms的是updateGS <$ eInput类型:

(<$)  :: a -> f b -> f a 
updateGS :: PlayerCommand -> GameState -> GameState 
eInput :: Event t PlayerCommand 

现在想想:什么类型必须abf被实例化为?

  1. 由于updateGS是第一个参数到<$其类型a,就必须有

    a ~ PlayerCommand -> GameState -> GameState 
    
  2. 同样,eInput是第二个参数,以<$其类型为f b,所以

    f b ~ Event t PlayerCommand 
    

    将应用程序类型关联到左侧,如此Event t PlayerCommand(Event t) PlayerCommand相同。因此,我们可以判断

    f ~ Event t 
    b ~ PlayerCommand 
    
  3. 放在一起的结果,f a的类型,我们可以看到,

    f a ~ Event t (PlayerCommand -> GameState -> GameState)  
    

因此,updateGS <$ eInput :: Event t (PlayerCommand -> GameState -> GameState),这也解释了错误类型。

+0

Upvote for the education,but see above for what happened when I tried to use <$>。 –