Closed cblp closed 2 years ago
I wrote some helpers for myself
botAction :: Update -> Model -> Maybe (Maybe Action)
botAction update model = Just <$> onUpdate update model
botHandler :: Maybe Action -> Model -> Eff (Maybe Action) Model
botHandler maction model =
case maction of
Nothing -> pure model
Just action -> onAction action model
(<#) :: model -> BotM a -> Eff (Maybe action) model
m <# b = withEffect (b $> Nothing) m
They don't help with extra iteration, but remove non-sense code.
It looks like ending
BotM
withpure NoAction
is boilerplate. As well ashandleAction NoAction = pure model
.
I agree, ergonomics might be slightly better, however I don't think using Nothing
instead of NoAction
is better.
At the same time,
botAction
allows for the absence of action withMaybe
in its signature.
Ideally that Maybe
should actually be something more sophisticated, e.g. Either UpdateParseError
. So Nothing
there does not have the same meaning as NoAction
.
Is
Eff
really needed?
Eff
ensures separation of "impure" BotM
actions from pure model updates.
How to send a message without an extra action?
You can use the helper (<#)
that you wrote, with Nothing
or NoAction
depending on your preference :)
Ideally that
Maybe
should actually be something more sophisticated, e.g.Either UpdateParseError
. SoNothing
there does not have the same meaning asNoAction
.
Why? How can the framework handle this instead of user code? I can imagine type Action = Either UpdateParseError GoodData
, but no -> Either UpdateParseError Action
Eff
ensures separation of "impure"BotM
actions from pure model updates.
But why [BotM action]
instead of BotM ()
?
Separation can be achieved through handleAction :: action -> model -> (BotM (), model)
How to send a message without an extra action?
You can use the helper
(<#)
that you wrote, withNothing
orNoAction
depending on your preference :)
Sorry, but no, that Nothing is inevitable re-issued and triggers handleAction an extra time.
Why? How can the framework handle this instead of user code?
Even if the user handles this, I think there should be a separate place for it.
But why
[BotM action]
instead ofBotM ()
?
The idea was that each BotM action
in that list is sort of independent and "atomic" in some sense. A single action might trigger several other things to be done (asynchronously). For example, if the user asks bot something, it can reply instantly, while processing the request in the background and maybe also updating status once in a while. That's an action triggering 3 other things (also as actions), one of which is repeated until the job is done. Current implementation runs BotM actions
sequentially and puts second generation actions in a queue which is then processed in the background, but that's an implementation detail.
Sorry, but no, that
Nothing
is inevitable re-issued and triggers handleAction an extra time.
I do not understand what you mean by "Nothing
is inevitable", sorry. Regarding handleAction
being triggered one extra time: first of all, this is not directly a problem (you have a check for Nothing
/NoAction
somewhere anyway), but I can see how putting lots of NoAction
s into a queue might not be ideal; secondly, this is a performance issue, which was never really considered in this library (the goal was to only present a TEA-like architecture for Telegram bots with some interesting higher-order features like bot transformations, see conversationBot
).
On the other hand note that NoOp
message/action used in many apps written in Elm (and miso
in Haskell) is very similar to NoAction
(of course NoAction
was inspired by NoOp
).
A single action might trigger several other things to be done (asynchronously).
Well, I didn't expect an asynchronous job framework in a simple bot library.
And it seems to miss exceptions.
For example, if the user asks bot something, it can reply instantly, while processing the request in the background and maybe also updating status once in a while.
As for me, forkIO
and async
suit better.
I do not understand what you mean by "Nothing is inevitable", sorry.
When I want to handle just one message and reply to it, I have to emit NoAction after reply, and then I have to handle that NoAction.
One can see in the debug log:
Incoming: SomeAction...
Incoming: NoAction
Should be fixed in https://hackage.haskell.org/package/telegram-bot-simple-0.4.
Maybe Action
returned.GetAction
existential introduced by @Player-205 to solve even more boilerplate.
It looks like ending BotM with
pure NoAction
is boilerplate. As well ashandleAction NoAction = pure model
.So, an extra action is always issued.
And user Action is always ~ Maybe Action'.
At the same time,
botAction
allows for the absence of action with Maybe in its signature.Is Eff really needed? How to send a message without an extra action?