Haskell ScottyM() 函数内的数据库查询

Haskell database query inside ScottyM() function

我正在尝试编写简单的休息 API。我使用 Database.SQLite.Simple、Scotty 和 Aeson。我在 ScottyM() 路由函数中遇到数据库查询问题。当我遇到这样的事情时

routes :: [User] -> ScottyM ()
routes allUsers = do
    get "/users/:id" $ do
        id <- param "id"
        json ([x | x <- allUsers, userId x == id] !! 0)

main = do
    conn <- open "data.db"
    users <- ( query_ conn "select id, first_name, second_name, team from users" :: IO [User] )
    scotty 3000 (routes users)

一切正常,但在这种情况下,allUsers 只会在服务器启动时更新一次。每次有人问起我都想问问。所以我写了这个:

routes :: Connection -> ScottyM ()
routes conn= do
   get "/users/:id" $ do
        id <- param "id"
        users <- ( query_ conn "select id, first_name, second_name, team from users" :: IO [User] )
        json (users !! id)

main = do
    conn <- open "data.db"
    scotty 3000 (routes conn)

我收到错误

Couldn't match expected type ‘Web.Scotty.Internal.Types.ActionT
                                Text IO [a0]’
            with actual type ‘IO [User]’
In a stmt of a 'do' block:
  users <- (query_
              conn "select id, first_name, second_name, team from users" ::
              IO [User])
In the second argument of ‘($)’, namely
  ‘do { id <- param "id";
        users <- (query_
                    conn "select id, first_name, second_name, team from users" ::
                    IO [User]);
        json (users !! id) }’
In a stmt of a 'do' block:
  get "/users/:id"
  $ do { id <- param "id";
         users <- (query_
                     conn "select id, first_name, second_name, team from users" ::
                     IO [User]);
         json (users !! id) }

如何解决?另外,如果我想要 select * from users where id = id from parameters?

,如何将参数传递给 sql 查询

get function's second argument is of type ActionM. If you investigate further, you'll see this is just shorthand for the more complicated looking ActionTeTextmIO

因为你的do块是这种类型的,你不能直接调用IO函数。您需要使用 liftIO 来获得正确的类型。因此,只需在 query_ 调用之前添加一个 liftIO 即可修复它。

项目 wiki 中有一个名为 using scotty with IO 的示例显示了这一点。