Monad 类型不匹配

dav*_*w15 1 monads haskell

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

\n\n
get "api/entities" $ do\n  entities <- loadEntities\n  let e1 : xs = entities\n  text $ note e1\n
Run Code Online (Sandbox Code Playgroud)\n\n

loadEntities有类型IO [Entity]

\n\n

错误是Couldn\'t match type \xe2\x80\x98ActionT IO ()\xe2\x80\x99 with \xe2\x80\x98t0 -> IO b0\xe2\x80\x99

\n\n

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

\n

Die*_*lan 5

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

如果你看一下get它的类型。

get :: MonadIO m => SpockRoute -> ActionT m () -> SpockT m ()
Run Code Online (Sandbox Code Playgroud)

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

liftIO :: IO a -> m a
Run Code Online (Sandbox Code Playgroud)

IO a这意味着您通过使用调用执行该堆栈中类型的每个函数liftIOActionT有一个 iso 的实例MonadIO,它是您在此处用于调用 IO 函数的实例。所以要打电话loadEntities你必须

entities <- liftIO loadEntities
Run Code Online (Sandbox Code Playgroud)

如果您结束了多次调用某个函数,您可以创建一个单独的模块,将其导入合格的模块并导出一个更友好的模块。

module Lifted (loadEntities) where

import qualified SomeModule as IO

loadEntities :: MonadIO m => m Entities
loadEntities = liftIO IO.loadEntities
Run Code Online (Sandbox Code Playgroud)

这将使您不必总是使用liftIO