Monad 类型不匹配

Monad type mismatch

我正在尝试在 Spock 应用程序中使用 IO monad。以下代码无法编译:

get "api/entities" $ do
  entities <- loadEntities
  let e1 : xs = entities
  text $ note e1

loadEntities 具有类型 IO [Entity]

错误是Couldn't match type ‘ActionT IO ()’ with ‘t0 -> IO b0’

Spock 使用 IO 以外的 monad 吗?如果是这样,我如何获得 loadEntities 的结果?

写下答案,以便人们可以看到更好的解释。

如果你看 get 它有类型。

get :: MonadIO m => SpockRoute -> ActionT m () -> SpockT m ()

ActionT 是一个 monad 转换器,它要求在内部 monad 中有一个 MonadIO 的实例。如果我们看一下类型类 MonadIO 它有一个函数

liftIO :: IO a -> m a

这意味着您使用 liftIO 在该堆栈中调用 IO a 类型的执行函数。 ActionT 也有一个 MonadIO 的实例,这就是您在此处用来调用 IO 函数的实例。所以要调用 loadEntities 你必须

entities <- liftIO loadEntities

如果你结束了对某个函数的调用,那么你可以创建一个单独的模块导入它合格并导出一个更友好的模块。

module Lifted (loadEntities) where

import qualified SomeModule as IO

loadEntities :: MonadIO m => m Entities
loadEntities = liftIO IO.loadEntities

这将使您不必总是使用 liftIO