Haskell中提取liftIO与runSql为独立函数的实现方案
Persist + Servant 代码复用问题解决
问题背景
使用Persist和Servant开发时,在某模块中定义了以下类型别名与数据库执行函数:
-- 便捷类型别名 type DbAction m a = ReaderT SqlBackend m a -- 使用连接池运行数据库查询 runSql :: DbAction (NoLoggingT (ResourceT IO)) a -> ConnectionPool -> IO a runSql = runSqlPersistMPool
但在另一个模块的Servant API实现中,出现了大量重复代码:
postUser :: UserCreate -> Handler Text postUser user = liftIO $ flip runSql pool $ do storeUser user getUser :: PathUserId -> Handler (Maybe User) getUser uid = liftIO $ flip runSql pool $ do fetchUser $ extractUserId uid
希望将重复的liftIO $ flip runSql pool $ ...逻辑提取为独立函数以减少冗余,但尝试过程中遇到阻碍。
失败的尝试
曾尝试以下实现,但SqlPersistT仅存在于Sqlite包中,引入了不必要的依赖:
runDbAction :: SqlPersistT IO a -> Handler a runDbAction action = liftIO $ flip runSql pool $ action
最终解决方案
改用核心persistent包提供的SqlPersistM类型(无需额外依赖),实现通用的数据库动作执行函数:
runDbAction :: SqlPersistM a -> Handler a runDbAction action = liftIO $ runSql action pool
内容的提问来源于stack exchange,提问作者igr
相关产品推荐
相关产品推荐

