Monad 在 StateT 上下文中转义

Monad escaping inside a StateT context

我正在尝试取回 json 提要中的值(通过 Aeson),直接位于 StateT 堆叠在 IO 中:

{-# LANGUAGE DeriveGeneric #-}
module MyFeed where

import Data.Aeson
import Network.URI (parseURI, URI(..))
import Data.Maybe (fromJust)
import Data.Text (Text, unpack)
import Control.Monad.State
import Network.HTTP
import GHC.Generics
import Control.Applicative
import Network.HTTP.Conduit (simpleHttp)
import qualified Data.ByteString.Lazy as B

type Feed a = StateT MyIndex IO a

data MyIndex = MyIndex {
    index :: Int
}

data FooBar = Foo | Bar

data MyFeed = MyFeed {
    idx :: !Text,
    key :: !Text
    } deriving (Show,Generic)

instance FromJSON MyFeed
instance ToJSON MyFeed

getJSON :: String -> IO B.ByteString
getJSON url = simpleHttp url

getFeed :: String -> IO (Maybe MyFeed)
getFeed url = (decode <$> getJSON url) :: IO (Maybe MyFeed)

getIndex :: FooBar -> Feed MyIndex
getIndex fb = do
  cursor <- get
  let newCursor = case fb of
                            Foo -> do  myFeed <- liftIO $ getFeed "http://echo.jsontest.com/key/value/idx/1"
                                       let i = read $ unpack $ idx $ fromJust myFeed
                                       return $ cursor { index = i }

                            Bar -> return cursor
  put newCursor
  return newCursor

Foo 的情况下,我按预期获取提要,但是当返回所需的值时,我得到:

src/MyFeed.hs:47:10:
    Couldn't match expected type ‘MyIndex’
                with actual type ‘m0 MyIndex’
    Relevant bindings include
      newCursor :: m0 MyIndex (bound at src/MyFeed.hs:40:7)
    In the first argument of ‘return’, namely ‘newCursor’
    In a stmt of a 'do' block: return newCursor

Actual Type 看起来仍然在 Monad 上下文中 (do {...})。有什么方法可以取出来还是我用错方法了?

错误是因为我使用了:

let newCursor = case fb of

而不是

newCursor <- case fb of

因此,最终值永远不会从其 monad 上下文中获取 "unwrapped"。