Haskell 缺少Monadstate实例

Haskell 缺少Monadstate实例,haskell,monads,state-monad,Haskell,Monads,State Monad,我正试图使用这个库来构建一个slackbot:,只是为了学习更多的haskell,并希望最终理解monads- 然后我有以下类型: data BotState = BotState { _appState :: AppState } makeLenses ''BotState type AppState = HM.Map String ChannelState emptyState :: AppState emptyState = HM.empty data Chan

我正试图使用这个库来构建一个slackbot:,只是为了学习更多的haskell,并希望最终理解monads-

然后我有以下类型:

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
我用以下工具运行我的机器人:

initApp = lookupEnv "SLACK_API_TOKEN" >>=
  \apiToken -> case apiToken of
    Nothing -> throwM ApiTokenMissingException
    Just t -> void $ Slack.runBot (Slack.SlackConfig t) runApp $ BotState emptyState
其中:

runApp :: Slack.Event -> Bot ()
runApp m@(Slack.Message cid uid body _ _ _) = sendMessage cid "GAH I CAN HAZ CHZBURGHER!" 
这运行良好,现在我希望添加更新系统状态的功能(通过增加计数器或以其他方式)

因此,我将modifyState函数添加到我的Bot:

modifyState :: (AppState -> AppState) -> Bot ()
modifyState f = uses Slack.userState $ view appState >>=
  \state -> modifying Slack.userState $ set appState $ f state 
这与:

 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’
鉴于
修改的签名,这是有意义的:

modifying :: MonadState s m => ASetter s s a b -> (a -> b) -> m ()
但是,在查看
Slack.userState
的文档时:

userState :: forall s s. Lens (SlackState s) (SlackState s) s s Source
然后:

data SlackState s

 ... Constructor ...
    Instances
Show s => Show (SlackState s)Source  
MonadState (SlackState s) (Slack s)Source   

那么为什么
BotState
还不是
MonadState
的实例呢?如何修复此问题?

$
运算符具有固定性0,而
>=
具有固定性
1
,因此这样的代码可以工作:

main :: IO ()
main = do
  putStrLn "hello world" >>= \_ -> putStrLn "hi"
但不是这个:

main :: IO ()
main = do
  putStrLn $ "hello world" >>= \_ -> putStrLn "hi"
它被解释为:

main :: IO ()
main = do
  putStrLn ("hello world" >>= \_ -> putStrLn "hi")
要查看固定性信息,请使用ghci的
:info
命令:

 :info $
($) ::
  forall (r :: ghc-prim-0.5.0.0:GHC.Types.RuntimeRep) a (b :: TYPE
                                                                r).
  (a -> b) -> a -> b
    -- Defined in ‘GHC.Base’
infixr 0 $
 :info >>=
class Applicative m => Monad (m :: * -> *) where
  (>>=) :: m a -> (a -> m b) -> m b
  ...
    -- Defined in ‘GHC.Base’
infixl 1 >>=

另外,如果您不确定,好的老括号总是在这里用于解救:)

$
运算符具有固定性0,而
>=
具有固定性
1
,因此这样的代码可以工作:

main :: IO ()
main = do
  putStrLn "hello world" >>= \_ -> putStrLn "hi"
但不是这个:

main :: IO ()
main = do
  putStrLn $ "hello world" >>= \_ -> putStrLn "hi"
它被解释为:

main :: IO ()
main = do
  putStrLn ("hello world" >>= \_ -> putStrLn "hi")
要查看固定性信息,请使用ghci的
:info
命令:

 :info $
($) ::
  forall (r :: ghc-prim-0.5.0.0:GHC.Types.RuntimeRep) a (b :: TYPE
                                                                r).
  (a -> b) -> a -> b
    -- Defined in ‘GHC.Base’
infixr 0 $
 :info >>=
class Applicative m => Monad (m :: * -> *) where
  (>>=) :: m a -> (a -> m b) -> m b
  ...
    -- Defined in ‘GHC.Base’
infixl 1 >>=

另外,如果您不确定,好的老括号总是在这里用于解救:)

因为它不是在寻找
MonadState(SlackState-BotState)BotState
,而是在寻找
MonadState(SlackState-BotState)((->)BotState)
。似乎是由于
$
>=
造成的优先级问题-请尝试显式括号。没错,这是由于
中的
$
使用Slack.userState$查看appState
造成的。将其更改为
将使用Slack.userState(查看appState)
修复该问题。我很想知道那里发生了什么?为什么在这种特殊情况下,
$
的行为不符合预期?顺便说一句,谢谢你的帮助,如果你想收集分数,把它写下来作为答案,然后得到一个upvote/accept:)非常粗略地说,你可以把
$
看作是在表达式的末尾加上括号。因此,
使用Slack.userState$stuff1>>=stuff2
使用Slack.userState(stuff1>>=stuff2)
,这是不需要的。请注意,在
do
块中,您不会遇到此问题:请尝试
do状态,因为它不是在查找
MonadState(SlackState BotState)BotState
,而是在查找
MonadState(SlackState BotState)((->)BotState)
。似乎是由于
$
>=
造成的优先级问题-请尝试显式括号。没错,这是由于
中的
$
使用Slack.userState$查看appState
造成的。将其更改为
将使用Slack.userState(查看appState)
修复该问题。我很想知道那里发生了什么?为什么在这种特殊情况下,
$
的行为不符合预期?顺便说一句,谢谢你的帮助,如果你想收集分数,把它写下来作为答案,然后得到一个upvote/accept:)非常粗略地说,你可以把
$
看作是在表达式的末尾加上括号。因此,
使用Slack.userState$stuff1>>=stuff2
使用Slack.userState(stuff1>>=stuff2)
,这是不需要的。请注意,在
do
块中,您不会遇到此问题:请尝试
do状态