9
我想写的是简化了编写使用持续,埃宋和斯科蒂持久性:CRUD类型类
这里一个CRUD后端一个类型类是我的想法:
runDB x = liftIO $ do info <- mysqlInfo
runResourceT $ SQL.withMySQLConn info $ SQL.runSqlConn x
class (J.FromJSON a, J.ToJSON a, SQL.PersistEntity a) => CRUD a where
getBasePath :: a -> String
getCrudName :: a -> String
getFromBody :: a -> ActionM a
getFromBody _ = do body <- jsonData
return body
mkInsertRoute :: a -> ScottyM()
mkInsertRoute el =
do post (fromString ((getBasePath el) ++ "/" ++ (getCrudName el))) $ do
body <- getFromBody el
runDB $ SQL.insert body
json $ J.Bool True
mkUpdateRoute :: a -> ScottyM()
mkDeleteRoute :: a -> ScottyM()
mkGetRoute :: a -> ScottyM()
mkGetAllRoute :: a -> ScottyM()
这并未“T编译,我得到这个错误:
Could not deduce (SQL.PersistEntityBackend a
~ Database.Persist.GenericSql.Raw.SqlBackend)
from the context (CRUD a)
bound by the class declaration for `CRUD'
at WebIf/CRUD.hs:(18,1)-(36,36)
Expected type: SQL.PersistEntityBackend a
Actual type: SQL.PersistMonadBackend
(SQL.SqlPersist (Control.Monad.Trans.Resource.ResourceT IO))
In the second argument of `($)', namely `SQL.insert body'
In a stmt of a 'do' block: runDB $ SQL.insert body
In the second argument of `($)', namely
`do { body <- getFromBody el;
runDB $ SQL.insert body;
json $ J.Bool True }'
似乎我不得不添加另一个类型约束,如PersistMonadBackend m ~ PersistEntityBackend a
,但我看不出如何。
谢谢! :-)我也结束了类似的事情,但我真的很喜欢它与所有Persistent后端一起工作,而不仅仅是基于SQL的后端。我知道当前的runDB强制执行此操作,所以我认为我可能需要更多的抽象。 – agrafix 2014-01-05 19:38:50
约束来自mkInsertRoute的默认实现。也许你应该从类定义中删除默认值,或者通过'runDB $ SQL.insert'位进行抽象? – 2014-01-05 19:47:52
我认为这足以通过'runDB'进行抽象了吗? – agrafix 2014-01-08 11:12:11