2016-11-23 73 views
1

使用servantpersistent库创建REST API,并使用insertUnique创建新实体时遇到类型不匹配错误。如何解决SqlBackend和PersistEntityBackend之间的类型不匹配?

这里是有问题的功能:

createUser :: Entity User -> App Int64 
createUser p = do 
    maybeNewUser <- runDb (insertUnique (User (userUsername $ entityVal p) (userSpotifyUser $ entityVal p))) 
    case maybeNewUser of 
     Nothing -> throwError err400 
     Just newUser -> return $ fromSqlKey newUser 

,出现以下错误:

Couldn't match expected type ‘persistent-2.2.4.1:Database.Persist.Sql.Types.SqlBackend’ 
     with actual type ‘persistent-2.2.4.1:Database.Persist.Class.PersistEntity.PersistEntityBackend 
          (String 
          -> String 
          -> time-1.5.0.1:Data.Time.Clock.UTC.UTCTime 
          -> time-1.5.0.1:Data.Time.Clock.UTC.UTCTime 
          -> User)’ 
In the first argument of ‘runDb’, namely 
[snip] 

而且参考,runDb功能:

runDb :: (MonadReader Config m, MonadIO m) => SqlPersistT IO b -> m b 
runDb query = do 
    pool <- asks getPool 
    liftIO $ runSqlPool query pool 

而且App NEWTYPE:

newtype App a = App 
    { runApp :: ReaderT Config (ExceptT ServantErr IO) a } deriving 
     (Functor, Applicative, Monad, MonadReader Config, MonadError ServantErr, MonadIO) 

我试过键入暗示insertUnique的结果为SqlBackend,但是这会导致一个同样令人困惑的错误。 SqlBackendPersistentEntityBackend类型是不可互换的吗?

或者monad的格式不正确?

任何帮助,非常感谢。

回答

1

我能够在this answer的帮助下找到它。

get等一样,insertUnique在此上下文中返回普通的User而不是Entity User

createUser :: User -> App Int64 
createUser p = do 
    user <- (User (userUsername $ entityVal p) (userSpotifyUser $ entityVal p)) 
    let insertUser = insertUnique user :: SqlPersistT IO (Maybe (Key User)) 
    maybeNewUserKey <- runDb insertUser 
    case maybeNewUserKey of 
     Nothing -> throwError err400 
     Just newUserKey -> 
      return $ fromSqlKey newUserKey 

使在事后更有意义,因为runDb接受SqlPersistT转化单子。

+0

所有这些间接性都让人困惑...... –

相关问题