我正在尝试自己学习HASKELL,我找到了这个页面https://www.parsonsmatt.org/2015/05/02/scotty_and_persistent.html 我尝试使用该代码,但出现错误:
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Products
name Text
description Text
price Int
deriving Show
|]
main :: IO ()
main = scotty 3000 $ do
Web.Scotty.middleware logStdoutDev
inAppDb $ do
doDbStuff
Web.Scotty.get "/api/products" $ json [(0::Int)..10]
inAppDb = liftIO . dbFunction
dbFunction query = runStderrLoggingT $
withPostgresqlPool connStr 10 $
\pool -> liftIO $ runSqlPersistMPool query pool
doDbStuff = do
res :: [Entity Products] <- selectList [] [LimitTo 1]
liftIO $ print res
错误
➜ my-project stack run
my-project> build (lib + exe)
Preprocessing library for my-project-0.1.0.0..
Building library for my-project-0.1.0.0..
ld: warning: -single_module is obsolete
Preprocessing executable 'my-project-exe' for my-project-0.1.0.0..
Building executable 'my-project-exe' for my-project-0.1.0.0..
[1 of 3] Compiling Main [Source file changed]
/Users/home/my-project/app/Main.hs:176:11: error:
• No instance for (Control.Monad.IO.Class.MonadIO
(Web.Scotty.Internal.Types.ScottyT
Data.Text.Internal.Lazy.Text IO))
arising from a use of ‘liftIO’
• In the first argument of ‘(.)’, namely ‘liftIO’
In the expression: liftIO . dbFunction
In an equation for ‘inAppDb’: inAppDb = liftIO . dbFunction
|
176 | inAppDb = liftIO . dbFunction
| ^^^^^^
Error: [S-7282]
Stack failed to execute the build plan.
While executing the build plan, Stack encountered the error:
[S-7011]
While building package my-project-0.1.0.0 (scroll up to its section to see the error) using:
/Users/home/.stack/setup-exe-cache/aarch64-osx/Cabal-simple_6HauvNHV_3.8.1.0_ghc-9.4.7 --verbose=1 --builddir=.stack-work/dist/aarch64-osx/ghc-9.4.7 build lib:my-project exe:my-project-exe --ghc-options " -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
我不知道为什么会出现这个错误:
liftIO .
你对此有什么想法吗?
提前致谢
阿伦
根据评论,Scotty 从 0.10 版本开始进行了重新设计,使
ScottyM
(和 ScottyT
)成为“仅配置”monad,它声明了 Web 服务器的中间件和路由,但无法执行 I/ O 本身。
因此,博客作者尝试使用
inAppDb
移入 Scotty 应用程序的任何数据库设置或其他 I/O 都将不起作用。相反,请删除 inAppDb
定义并将该设置移至 main
,然后再调用 scotty
。对于您的具体代码示例,它将如下所示:
main :: IO ()
main = do
dbFunction $ do
doDbStuff
scotty 3000 $ do
Web.Scotty.middleware logStdoutDev
Web.Scotty.get "/api/products" $ json [(0::Int)..10]
就博客文章的其余部分而言,无论如何,作者似乎在第 2 部分中放弃了整个
inAppDb
,并且 inHandlerDb
调用应该都能正常工作。它们在 ActionM
monad 中运行,该 monad 通过 liftIO
支持 I/O 操作,因此应该对如下示例进行类型检查:
import qualified Web.Scotty as S
import qualified Data.Text.Lazy as T
inHandlerDb = liftIO . dbFunction
main :: IO ()
main = do
dbFunction $ do
doMigrations
doDbStuff
S.scotty 3000 $ do
S.middleware logStdoutDev
S.get "/" $ S.html "Hello World"
S.get "/products" $ do
products <- inHandlerDb $ selectList [] []
S.html (T.pack $ show $ length (products :: [Entity Products]))