我一直在尝试让一个与 scotty 一起运行的 Web 服务器,它可以使用 selda 与我的数据库通信。我认为使用单子变压器堆栈将是完成类似事情的方法。我一直在努力解决它,但我遇到了一些死胡同,这些类型似乎不可行。
{-# LANGUAGE DeriveGeneric, OverloadedStrings, OverloadedLabels #-}
module Server where
import Web.Scotty
import Data.Monoid (mconcat)
import Data.Aeson (ToJSON)
import GHC.Generics
import Web.Scotty
import Database.Selda
import Database.Selda.SQLite
import Control.Monad.Trans.Class
import Models
type App = SeldaT SQLite ScottyM
-- withPersist:: (MonadIO m, MonadMask m) => SeldaT SQLite m a -> m a
server = scotty 4200 (withPersist router)
router :: App ()
router = do
lift $ get "/book/:id" searchBook
searchBook:: ActionM ()
searchBook = do
books <- query selectBookQuery
json books
where
selectBookQuery = do
book <- select goodreadsBooks
restrict (book ! #goodreadsId .== "20")
return book
我试图将它从这里的答案松散地建立起来,但我想包装路由器而不是单独的路由。withPersist
我不希望我打开的连接数与我拥有的路由数成正比,如果我可以避免的话,我不希望每条路由都必须有一个呼叫。
所以我有一个App
which 是 type SeldaT Sqlite ScottyM
,并使用withPersist
(即 == withSQLite "mydb.db"
),我会把它SeldaT Sqlite ScottyM
变成一个ScottyM
. 不过问题还是挺多的,以下是我对它们的理解:
SeldaT m a
受 约束(MonadIO m, MonadMask m)
,并且 ScottyM 没有MonadIO
Scotty.get
返回 aScottyM ()
,我觉得这是我lift
用来把它变成 a 的地方SeldaT Sqlite ScottyM
,但是我得到了一个错误,可能与ScottyM
不是MonadIO
来自上面的实例有关。- 由于
searchBook
仍然是一个ActionM
,我无法在其中运行查询。不确定如何get
接受我的变压器堆栈而不是ActionM
以下是错误:
/home/marcus/Documents/projects/nowwhatdoiread/nwdir-server/app/Server.hs:19:23: error:
• No instance for (MonadIO ScottyM)
arising from a use of ‘withPersist’
• In the second argument of ‘scotty’, namely ‘(withPersist router)’
In the expression: scotty 4200 (withPersist router)
In an equation for ‘server’:
server = scotty 4200 (withPersist router)
|
19 | server = scotty 4200 (withPersist router)
| ^^^^^^^^^^^^^^^^^^
/home/marcus/Documents/projects/nowwhatdoiread/nwdir-server/app/Server.hs:23:3: error:
• No instance for (MonadTrans (SeldaT SQLite))
arising from a use of ‘lift’
• In a stmt of a 'do' block: lift $ get "/book/:id" searchBook
In the expression: do lift $ get "/book/:id" searchBook
In an equation for ‘router’:
router = do lift $ get "/book/:id" searchBook
|
23 | lift $ get "/book/:id" searchBook
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/home/marcus/Documents/projects/nowwhatdoiread/nwdir-server/app/Server.hs:27:12: error:
• No instance for (MonadSelda
(Web.Scotty.Internal.Types.ActionT
Data.Text.Internal.Lazy.Text IO))
arising from a use of ‘query’
• In a stmt of a 'do' block: books <- query selectBookQuery
In the expression:
do books <- query selectBookQuery
json books
In an equation for ‘searchBook’:
searchBook
= do books <- query selectBookQuery
json books
where
selectBookQuery
= do book <- select goodreadsBooks
....
|
27 | books <- query selectBookQuery
| ^^^^^^^^^^^^^^^^^^^^^
更新:在查看了一些类似的问题之后,我可能需要使用 ScottyT。不确定如何将 SeldaT 嵌套在 ScottyT 变压器中。