I am trying to learn HASKELL by myself, I have found this page https://www.parsonsmatt.org/2015/05/02/scotty_and_persistent.html and I have tried to use the code but I got an error:
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
Error
➜ 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
I do not know why the error is here:
liftIO .
Do you have any ideas on it?
Thanks in advance
Aron
As per the comments, Scotty was redesigned starting with version 0.10 to make ScottyM
(and ScottyT
) into a "configuration only" monad that declares the middleware and routing of the web server but isn't capable of performing I/O itself.
So, any database setup or other I/O that the blog author has tried to move into the Scotty app using inAppDb
isn't going to work. Instead, delete the inAppDb
definition and move that setup into main
before invoking scotty
. For your specific code example, it'll look like this:
main :: IO ()
main = do
dbFunction $ do
doDbStuff
scotty 3000 $ do
Web.Scotty.middleware logStdoutDev
Web.Scotty.get "/api/products" $ json [(0::Int)..10]
As far as the rest of the blog post is concerned, it looks like the author abandons the whole inAppDb
by part 2 anyway, and the inHandlerDb
calls should all work fine. They are operating in the ActionM
monad, which supports I/O operations via liftIO
, so examples like the following should typecheck:
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]))