1

我正在关注教程,它使用 scotty 和持久性来创建一个简单的 API。

但是,我正在尝试使用 scotty 和 mysql 简单库创建一个简单的 api。

现在我被困在代码中的某一点。

在下面的代码中,我无法将getUser函数转换为键入“ActionT Error ConfigM”,因为我的代码失败了。

谁能帮助我了解如何转换 getUser 函数以实现所需的类型签名?

代码

type Error = Text
type Action = ActionT Error ConfigM ()

config :: Config
config = Config
    { environment = Development 
     ,db1Conn = connect connectionInfo
    }

main :: IO ()
main = do
  runApplication config

runApplication :: Config -> IO ()
runApplication c = do
  o <- getOptions (environment c)
  let r m = runReaderT (runConfigM m) c
  scottyOptsT o r application

application :: ScottyT Error ConfigM ()
application = do
  e <- lift (asks environment)
  get "/user" getTasksA

getTasksA :: Action
getTasksA = do
    u <- getUser
    json u 

getUser :: IO User
getUser = do
  e <- asks environment
  conn <- db1Conn config 
  [user]<- query_ conn "select login as userId, email as userEmail from member limit 1"
  return user 

错误

• Couldn't match type ‘IO’ with ‘ActionT Error ConfigM’
      Expected type: ActionT Error ConfigM User
        Actual type: IO User
    • In a stmt of a 'do' block: u <- getUser
      In the expression:
        do { u <- getUser;
             json u }
      In an equation for ‘getTasksA’:
          getTasksA
            = do { u <- getUser;
                   json u }
4

1 回答 1

2

您遗漏了大量代码(导入和编译User指示以及.

但现在你的问题:

我会将Action类型更改为以下

type Action a = ActionT Error ConfigM a

然后getTasksA具有以下类型签名

getTasksA :: Action ()
getTasksA = do
    u <- getUser
    json u 

(或者你可以把它写成getTasksA = getUser >>= json

getUser

getUser :: Action User
getUser = do
  e <- asks environment
  conn <- db1Conn config 
  [user] <- liftIO $ query_ conn "select login as userId, ..."
  return user

几点说明

  • [user] <- liftIO $ query ..是个坏主意 - 如果没有找到用户,这会使您的应用程序崩溃 - 尝试编写总函数和模式匹配。最好返回一个Maybe User.

    getUser :: Action (Maybe User)
    getUser = do
      e <- asks environment
      conn <- db1Conn config 
      fmap listToMaybe . liftIO $ query_ conn "select login as userId, ..."
    
  • 如果您可以绕开它,而不是使用persistent手动编写 SQL 查询,这很容易出错,尤其是在重构时,想象一下重命名userIduserID.

  • ask用了几次,environment然后就不用了。编译-Wall甚至-Werror获得警告甚至提升警告以编译错误(这对于生产设置是一个好主意。

于 2017-12-12T21:34:02.130 回答