Functional reactive confusion of banana type

Heinrich Apfelmus generously intervened in this problem . I considered using accumB as a solution, but thought there would be a type error. In any case, having tried his suggestion, I got a type error.

 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' 

So, I learned (<$) and mixed up with a partial application. Looked at his examples. The more I did this, the more I thought that the code above should work, and I am confused why it does not.

This is what I think should happen:

since (<$) is of type (<$) :: a -> fb -> fa

and updateGS is of type updateGS :: PlayerCommand -> GameState -> GameState

and eInput is of type Event t PlayerCommand

then do not updateGS <$ eInput yield

Event t (GameState -> GameState) ?

My reasoning is spoiled somewhere, can someone indicate where?

Update: when I tried to use (<$>) , I got the following error:

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 

for reference, here is the whole function

 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 
+4
source share
1 answer

What's wrong with the code

You should use <$> , not <$ .

  • <$> , aka fmap applies the function to the value of the events of the right side, what are you trying to do in this case.
  • <$ replaces the value of the events of the right side with the left side, giving you an event that occurs simultaneously with the original, but always contains the same value.

    Note: x <$ e same as const x <$> e .

Why your reasoning is wrong

We are trying to determine the type updateGS <$ eInput , where the types of subterm are:

 (<$) :: a -> fb -> fa updateGS :: PlayerCommand -> GameState -> GameState eInput :: Event t PlayerCommand 

Now think: what types should a , b and f be created on?

  • Since updateGS is the first argument <$ , which has type a , we must have

     a ~ PlayerCommand -> GameState -> GameState 
  • Similarly, eInput is the second argument <$ , which is of type fb , therefore

     fb ~ Event t PlayerCommand 

    Map the applications to the left, so Event t PlayerCommand same as (Event t) PlayerCommand . Therefore, we can determine that

     f ~ Event t b ~ PlayerCommand 
  • Comparing the result type, fa , we see that

     fa ~ Event t (PlayerCommand -> GameState -> GameState) 

Therefore, updateGS <$ eInput :: Event t (PlayerCommand -> GameState -> GameState) , which explains the type error.

+5
source

Source: https://habr.com/ru/post/1442129/


All Articles