haskell Scotty:没有MonadIO ScottyT的示例(由使用'liftIO'引起)

mbskvtky  于 2024-01-08  发布在  其他
关注(0)|答案(2)|浏览(220)

我试图自己学习HASKELL,我发现了这个页面https://www.parsonsmatt.org/2015/05/02/scotty_and_persistent.html,我试图使用代码,但我得到了一个错误:

  1. share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
  2. Products
  3. name Text
  4. description Text
  5. price Int
  6. deriving Show
  7. |]
  8. main :: IO ()
  9. main = scotty 3000 $ do
  10. Web.Scotty.middleware logStdoutDev
  11. inAppDb $ do
  12. doDbStuff
  13. Web.Scotty.get "/api/products" $ json [(0::Int)..10]
  14. inAppDb = liftIO . dbFunction
  15. dbFunction query = runStderrLoggingT $
  16. withPostgresqlPool connStr 10 $
  17. \pool -> liftIO $ runSqlPersistMPool query pool
  18. doDbStuff = do
  19. res :: [Entity Products] <- selectList [] [LimitTo 1]
  20. liftIO $ print res

字符串
误差

  1. my-project stack run
  2. my-project> build (lib + exe)
  3. Preprocessing library for my-project-0.1.0.0..
  4. Building library for my-project-0.1.0.0..
  5. ld: warning: -single_module is obsolete
  6. Preprocessing executable 'my-project-exe' for my-project-0.1.0.0..
  7. Building executable 'my-project-exe' for my-project-0.1.0.0..
  8. [1 of 3] Compiling Main [Source file changed]
  9. /Users/home/my-project/app/Main.hs:176:11: error:
  10. No instance for (Control.Monad.IO.Class.MonadIO
  11. (Web.Scotty.Internal.Types.ScottyT
  12. Data.Text.Internal.Lazy.Text IO))
  13. arising from a use of liftIO
  14. In the first argument of ‘(.)’, namely liftIO
  15. In the expression: liftIO . dbFunction
  16. In an equation for inAppDb’: inAppDb = liftIO . dbFunction
  17. |
  18. 176 | inAppDb = liftIO . dbFunction
  19. | ^^^^^^
  20. Error: [S-7282]
  21. Stack failed to execute the build plan.
  22. While executing the build plan, Stack encountered the error:
  23. [S-7011]
  24. While building package my-project-0.1.0.0 (scroll up to its section to see the error) using:
  25. /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"
  26. Process exited with code: ExitFailure 1


我不知道为什么会出现错误:liftIO .
你对此有什么想法吗?
Thanks in advance
Aron

jdzmm42g

jdzmm42g1#

根据评论,Scotty从0.10版本开始重新设计,使ScottyM(和ScottyT)成为一个“仅配置”的monad,它声明了Web服务器的中间件和路由,但本身不能执行I/O。
因此,博客作者试图使用inAppDb将任何数据库设置或其他I/O移动到Scotty应用程序中都不会工作。相反,在调用scotty之前删除inAppDb定义并将该设置移动到main中。对于您的特定代码示例,它看起来像这样:

  1. main :: IO ()
  2. main = do
  3. dbFunction $ do
  4. doDbStuff
  5. scotty 3000 $ do
  6. Web.Scotty.middleware logStdoutDev
  7. Web.Scotty.get "/api/products" $ json [(0::Int)..10]

字符串
就博客文章的其余部分而言,看起来作者在第2部分放弃了整个inAppDbinHandlerDb调用应该都能正常工作。它们在ActionM monad中运行,该monad支持通过liftIO进行I/O操作,因此下面的示例应该进行类型检查:

  1. import qualified Web.Scotty as S
  2. import qualified Data.Text.Lazy as T
  3. inHandlerDb = liftIO . dbFunction
  4. main :: IO ()
  5. main = do
  6. dbFunction $ do
  7. doMigrations
  8. doDbStuff
  9. S.scotty 3000 $ do
  10. S.middleware logStdoutDev
  11. S.get "/" $ S.html "Hello World"
  12. S.get "/products" $ do
  13. products <- inHandlerDb $ selectList [] []
  14. S.html (T.pack $ show $ length (products :: [Entity Products]))

展开查看全部
l5tcr1uw

l5tcr1uw2#

我终于完成了我的代码。我现在有一个Haskell的例子,使用Scotty,Persistent(Postgresql)和一个返回JSON数据的GET方法。
下面是完整的代码:

  1. {-# LANGUAGE GADTs #-}
  2. {-# LANGUAGE GeneralizedNewtypeDeriving #-}
  3. {-# LANGUAGE MultiParamTypeClasses #-}
  4. {-# LANGUAGE OverloadedStrings #-}
  5. {-# LANGUAGE QuasiQuotes #-}
  6. {-# LANGUAGE TemplateHaskell #-}
  7. {-# LANGUAGE TypeFamilies #-}
  8. {-# LANGUAGE DataKinds #-}
  9. {-# LANGUAGE FlexibleInstances #-}
  10. {-# LANGUAGE DerivingStrategies #-}
  11. {-# LANGUAGE StandaloneDeriving #-}
  12. {-# LANGUAGE UndecidableInstances #-}
  13. {-# LANGUAGE ScopedTypeVariables #-}
  14. {-# LANGUAGE DeriveGeneric #-}
  15. {-# LANGUAGE RecordWildCards #-}
  16. module Main (main) where
  17. import Control.Monad.Trans.Reader (ReaderT)
  18. import Control.Monad.Trans.Resource (ResourceT)
  19. import Control.Monad.IO.Class (liftIO)
  20. import Control.Monad.Logger (runStdoutLoggingT, NoLoggingT)
  21. import Database.Persist
  22. import Database.Persist.TH (share, mkPersist, sqlSettings, mkMigrate, persistLowerCase)
  23. import Database.Persist.Postgresql (ConnectionString, SqlBackend, runMigration, runSqlPersistMPool, withPostgresqlPool)
  24. import GHC.Generics
  25. import Web.Scotty (html, delete, get, post, put, scotty, ActionM, json, text, middleware)
  26. import Data.Aeson (FromJSON(..), ToJSON(..), (.:), (.=), pairs, object, withObject)
  27. import Data.Text
  28. import Network.Wai.Middleware.RequestLogger (logStdoutDev)
  29. share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
  30. Products sql=products
  31. name Text
  32. description Text
  33. price Int
  34. deriving Show Eq Generic
  35. |]
  36. connStr :: Database.Persist.Postgresql.ConnectionString
  37. connStr = "host=localhost dbname=example user=postgres password=postgres port=5432"
  38. inBackend :: ReaderT SqlBackend (NoLoggingT (ResourceT IO)) a-> IO a
  39. inBackend action = runStdoutLoggingT $ withPostgresqlPool connStr 10 $ \pool -> liftIO $ do
  40. flip runSqlPersistMPool pool $ do
  41. -- runMigration migrateAll
  42. action
  43. instance ToJSON (Entity Products) where
  44. toJSON (Entity productId (c@Products{..})) =
  45. object
  46. [ "id" .= productId
  47. , "name" .= productsName
  48. , "price" .= productsPrice
  49. , "description" .= productsDescription
  50. ]
  51. main :: IO ()
  52. main = do
  53. scotty 3000 $ do
  54. Web.Scotty.middleware logStdoutDev
  55. Web.Scotty.get "/api/products" $ do
  56. (products :: [Entity Products]) <-
  57. liftIO $ inBackend $ selectList [] []
  58. json products

字符串
我还分享了我使用过的依赖项列表及其各自的版本:

  1. dependencies:
  2. - base >= 4.7 && < 5
  3. - text
  4. - containers
  5. - monad-logger
  6. - postgresql-simple
  7. - persistent
  8. - persistent-postgresql
  9. - persistent-template
  10. - esqueleto
  11. - uuid
  12. - mtl
  13. - time
  14. - exceptions
  15. - unliftio-core
  16. - transformers
  17. - resourcet
  18. - scotty
  19. - blaze-html
  20. - aeson
  21. - wai-extra
  22. my-project stack ls dependencies
  23. Cabal 3.8.1.0
  24. Cabal-syntax 3.8.1.0
  25. HUnit 1.6.2.0
  26. OneTuple 0.4.1.1
  27. Only 0.1
  28. QuickCheck 2.14.3
  29. StateVar 1.2.2
  30. aeson 2.1.2.1
  31. ansi-terminal 0.11.5
  32. ansi-terminal-types 0.11.5
  33. appar 0.1.8
  34. array 0.5.4.0
  35. asn1-encoding 0.9.6
  36. asn1-parse 0.9.5
  37. asn1-types 0.3.4
  38. assoc 1.1
  39. async 2.2.4
  40. attoparsec 0.14.4
  41. attoparsec-aeson 2.1.0.0
  42. attoparsec-iso8601 1.1.0.0
  43. auto-update 0.1.6
  44. base 4.17.2.0
  45. base-compat 0.12.3
  46. base-compat-batteries 0.12.3
  47. base-orphans 0.9.1
  48. base64-bytestring 1.2.1.0
  49. basement 0.0.16
  50. bifunctors 5.5.15
  51. binary 0.8.9.1
  52. bitvec 1.1.5.0
  53. blaze-builder 0.4.2.3
  54. blaze-html 0.9.1.2
  55. blaze-markup 0.8.3.0
  56. bsb-http-chunked 0.0.0.4
  57. byteorder 1.0.4
  58. bytestring 0.11.5.2
  59. bytestring-builder 0.10.8.2.0
  60. cabal-doctest 1.0.9
  61. call-stack 0.4.0
  62. case-insensitive 1.2.1.0
  63. colour 2.3.6
  64. comonad 5.0.8
  65. conduit 1.3.5
  66. conduit-extra 1.3.6
  67. containers 0.6.7
  68. contravariant 1.5.5
  69. cookie 0.4.6
  70. cryptohash-md5 0.11.101.0
  71. cryptohash-sha1 0.11.101.0
  72. cryptonite 0.30
  73. data-default-class 0.1.2.0
  74. data-fix 0.3.2
  75. deepseq 1.4.8.0
  76. directory 1.3.7.1
  77. distributive 0.6.2.1
  78. dlist 1.0
  79. easy-file 0.2.5
  80. entropy 0.4.1.10
  81. esqueleto 3.5.11.0
  82. exceptions 0.10.5
  83. fast-logger 3.2.2
  84. filepath 1.4.2.2
  85. foldable1-classes-compat 0.1
  86. generically 0.1.1
  87. ghc-bignum 1.3
  88. ghc-boot-th 9.4.7
  89. ghc-prim 0.9.1
  90. hashable 1.4.3.0
  91. hourglass 0.2.12
  92. http-api-data 0.5
  93. http-date 0.0.11
  94. http-types 0.12.3
  95. http2 4.1.4
  96. indexed-traversable 0.1.3
  97. indexed-traversable-instances 0.1.1.2
  98. integer-gmp 1.1
  99. integer-logarithms 1.0.3.1
  100. iproute 1.7.12
  101. lift-type 0.1.1.1
  102. lifted-base 0.2.3.12
  103. memory 0.18.0
  104. microlens 0.4.13.1
  105. microlens-th 0.4.3.14
  106. monad-control 1.0.3.1
  107. monad-logger 0.3.40
  108. monad-loops 0.4.3
  109. mono-traversable 1.0.15.3
  110. mtl 2.2.2
  111. my-project 0.1.0.0
  112. network 3.1.4.0
  113. network-byte-order 0.1.7
  114. network-info 0.2.1
  115. old-locale 1.0.0.7
  116. old-time 1.1.0.3
  117. parsec 3.1.16.1
  118. path-pieces 0.2.1
  119. pem 0.2.4
  120. persistent 2.14.6.0
  121. persistent-postgresql 2.13.6.1
  122. persistent-template 2.12.0.0
  123. postgresql-libpq 0.9.5.0
  124. pretty 1.1.3.6
  125. primitive 0.8.0.0
  126. process 1.6.17.0
  127. psqueues 0.2.8.0
  128. random 1.2.1.1
  129. recv 0.1.0
  130. regex-base 0.94.0.2
  131. regex-compat 0.95.2.1
  132. regex-posix 0.96.0.1
  133. resource-pool 0.4.0.0
  134. resourcet 1.2.6
  135. rts 1.0.2
  136. safe-exceptions 0.1.7.4
  137. scientific 0.3.7.0
  138. scotty 0.12.1
  139. semialign 1.3
  140. semigroupoids 5.3.7
  141. silently 1.2.5.3
  142. simple-sendfile 0.2.32
  143. split 0.2.3.5
  144. splitmix 0.1.0.5
  145. stm 2.5.1.0
  146. stm-chans 3.0.0.9
  147. streaming-commons 0.2.2.6
  148. strict 0.5
  149. string-conversions 0.4.0.1
  150. tagged 0.8.7
  151. template-haskell 2.19.0.0
  152. text 2.0.2
  153. text-short 0.1.5
  154. th-abstraction 0.4.5.0
  155. th-lift 0.8.4
  156. th-lift-instances 0.1.20
  157. these 1.2
  158. time 1.12.2
  159. time-compat 1.9.6.1
  160. time-manager 0.0.1
  161. transformers 0.5.6.2
  162. transformers-base 0.4.6
  163. transformers-compat 0.7.2
  164. typed-process 0.2.11.1
  165. unix 2.7.3
  166. unix-compat 0.7
  167. unix-time 0.4.11
  168. unliftio 0.2.25.0
  169. unliftio-core 0.2.1.0
  170. unordered-containers 0.2.19.1
  171. utf8-string 1.0.2
  172. uuid 1.3.15
  173. uuid-types 1.0.5.1
  174. vault 0.3.1.5
  175. vector 0.13.1.0
  176. vector-algorithms 0.9.0.1
  177. vector-stream 0.1.0.0
  178. wai 3.2.3
  179. wai-extra 3.1.13.0
  180. wai-logger 2.4.0
  181. warp 3.3.25
  182. witherable 0.4.2
  183. word8 0.1.3
  184. x509 1.7.7
  185. zlib 0.6.3.0


这是我的第一个代码,所以我会继续改进它,以便更多地了解Haskell(欢迎所有提示和技巧!)。
最后,我想感谢大家抽出时间回答我最初的问题。

展开查看全部

相关问题