Scotty:没有 MonadIO ScottyT 的实例(由于使用“liftIO”而产生)

问题描述 投票:0回答:1

我正在尝试自己学习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 .

你对此有什么想法吗?

提前致谢

阿伦

haskell haskell-stack
1个回答
0
投票

根据评论,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]))
© www.soinside.com 2019 - 2024. All rights reserved.