我试图在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的结果?
答案 0 :(得分:4)
写答案让人们可以看到更好的解释。
如果你看get
它有类型。
get :: MonadIO m => SpockRoute -> ActionT m () -> SpockT m ()
ActionT
是一个monad转换器,它在内部monad中需要一个MonadIO
的实例。如果我们查看类型类MonadIO
它有一个函数
liftIO :: IO a -> m a
这意味着您调用的每个函数都使用IO a
执行该堆栈中liftIO
类型的函数。 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