ich eine slackbot mit dieser Bibliothek zu bauen bin versucht: https://hackage.haskell.org/package/slack-api, nur ein wenig mehr Haskell, zu lernen und hoffentlich endlich verstehen Monaden -_-.Fehlende Monadstate Instanz
ich dann die folgenden Typen haben:
data BotState = BotState
{
_appState :: AppState
}
makeLenses ''BotState
type AppState = HM.Map String ChannelState
emptyState :: AppState
emptyState = HM.empty
data ChannelState = ChannelState
{ _counter :: Int}
type Bot = Slack.Slack BotState
und ich betreibe meine bot mit:
initApp = lookupEnv "SLACK_API_TOKEN" >>=
\apiToken -> case apiToken of
Nothing -> throwM ApiTokenMissingException
Just t -> void $ Slack.runBot (Slack.SlackConfig t) runApp $ BotState emptyState
wo:
runApp :: Slack.Event -> Bot()
runApp [email protected](Slack.Message cid uid body _ _ _) = sendMessage cid "GAH I CAN HAZ CHZBURGHER!"
Dieses feine läuft, jetzt möchte ich hinzufügen die Fähigkeit, den Systemzustand zu aktualisieren (durch Inkrementieren des Zählers oder auf andere Weise).
so eine modifyState Funktion meiner Bot ich hinzufügen:
modifyState :: (AppState -> AppState) -> Bot()
modifyState f = uses Slack.userState $ view appState >>=
\state -> modifying Slack.userState $ set appState $ f state
Dies bricht mit:
No instance for (Control.Monad.State.Class.MonadState
(Slack.SlackState BotState) ((->) BotState))
arising from a use of ‘modifying’
In the expression: modifying Slack.userState
In the expression:
modifying Slack.userState $ set appState $ f state
In the second argument of ‘(>>=)’, namely
‘\ state -> modifying Slack.userState $ set appState $ f state’
Welche Sinn die Signatur für modifying
gegeben macht:
modifying :: MonadState s m => ASetter s s a b -> (a -> b) -> m()
jedoch auf für Slack.userState
in der Dokumentation suchen:
userState :: forall s s. Lens (SlackState s) (SlackState s) s s Source
Und dann:
data SlackState s
... Constructor ...
Instances
Show s => Show (SlackState s)Source
MonadState (SlackState s) (Slack s)Source
Also warum dann nicht die BotState
bereits eine Instanz von MonadState
? Wie könnte ich das beheben?
Weil es nicht sucht' MonadState (SlackState BotState) BotState ', es sucht' MonadState (SlackState BotState) ((->) BotState) '. Scheint wie ein Präzedenzfall aufgrund '$' und '>> =' - explizite Klammern zu versuchen. – user2407038
Du hast Recht, es war wegen der '$' in 'verwendet Slack.userState $ view appState'. Ändern dass 'verwendet Slack.userState (Ansicht AppState)' das Problem behebt. Ich würde gerne verstehen, was dort passiert ist? Warum hat sich das '$' in dieser speziellen Situation nicht wie erwartet verhalten? Vielen Dank für Ihre Hilfe, wenn Sie die Punkte sammeln möchten, schreiben Sie es als Antwort auf und erhalten Sie eine positive Bewertung/Annahme :) –
Sehr grob kann man sich '$' vorstellen, indem man bis zum Ende Klammern hinzufügt der Ausdruck. Also, 'verwendet Slack.userState $ stuff1 >> = stuff2' ist' verwendet Slack.userState (stuff1 >> = stuff2) 'was nicht beabsichtigt war. Beachten Sie, dass Sie in einem 'do'-Block dieses Problem nicht haben: versuchen Sie' do state <- verwendet Slack.userState $ view appState; modifizieren Slack.userState $ set appState $ f state'. Sie können eine neue Zeile anstelle von ';' verwenden, solange Sie sie richtig einrücken ('state <-' und' modifying 'sollten in derselben Spalte beginnen) – chi