Haskell GET 路由 ActionCtxT 错误中的 Spock IO
Haskell Spock IO within GET Route ActionCtxT Error
我尝试 return 网络应用程序(Spock 网络服务器)路由定义中的 uuid。
路由很容易定义
get("PATH") $ do
text "Hello World"
现在我尝试从 Data.UUID.V1 模块通过 nextRandom
return 一个 uuid。
函数 return 是一个 IO(Maybe UUID)
值。
所以我想,因为我在 IO 中并与另一个 IO 一起工作,所以我必须简单地将值与 <-
绑定,就像这样:
get ("id") $ do
uuid<-nextUUID
json . pack $ show $ uuid
但是编译器说不:
Couldn't match type ‘ActionCtxT ctx0 m0’ with ‘IO’
Expected type: IO b0
Actual type: ActionCtxT ctx0 m0 b0
• In a stmt of a 'do' block: json . pack $ show $ uuid
In the second argument of ‘($)’, namely
‘do { uuid <- nextUUID;
json . pack $ show $ uuid }’
为什么会抛出该错误?
我可以使用一个简单的打印示例轻松创建 uuid,但在 Spock 中,我不明白 ActionCtxT 的作用以及为什么我不能在其中执行 uuid IO。
So I thought, since I am in IO and work with another IO
这就是问题所在,当您在 Spock 中进行路由时,您不在 IO 中。错误消息告诉您您真正处于什么环境:ActionCtxT ctx0 m0
。根据 the docs, that's a monad transformer stack 捆绑效果和状态。
您可以 "lift" 使用 liftIO
将 IO 计算转换为正确的类型。
get ("id") $ do
uuid <- liftIO nextUUID
json . pack $ show $ uuid
根据 Libbys 的有用回答,我刚刚添加了 Maybe UUID
的 Nothing
的捕获。这里是完整的程序:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Web.Spock hiding (head)
import Web.Spock.Config
import Data.UUID.V1
import Data.Pool
import Control.Monad.IO.Class
import Database.PostgreSQL.Simple
import Data.Aeson (Value(Null))
import qualified Network.HTTP.Types.Status as Http
type AppAction a = SpockActionCtx () Connection AppSession AppState a
data AppState = EmptyState
data AppSession = EmptySession
main :: IO ()
main =
do pool<-createPool (connect (ConnectInfo "localhost" 5432 "" "" "envelopes") ) close 1 10 10
spockCfg <- defaultSpockCfg EmptySession (PCPool pool) EmptyState
runSpock 8080 (spock spockCfg app)
app :: SpockM Connection AppSession AppState ()
app = do
get ("json/id") $ do
uuid<-liftIO nextUUID
case uuid of
Nothing -> do
setStatus Http.status500
json Null
Just x -> json $ show x
我尝试 return 网络应用程序(Spock 网络服务器)路由定义中的 uuid。
路由很容易定义
get("PATH") $ do
text "Hello World"
现在我尝试从 Data.UUID.V1 模块通过 nextRandom
return 一个 uuid。
函数 return 是一个 IO(Maybe UUID)
值。
所以我想,因为我在 IO 中并与另一个 IO 一起工作,所以我必须简单地将值与 <-
绑定,就像这样:
get ("id") $ do
uuid<-nextUUID
json . pack $ show $ uuid
但是编译器说不:
Couldn't match type ‘ActionCtxT ctx0 m0’ with ‘IO’
Expected type: IO b0
Actual type: ActionCtxT ctx0 m0 b0
• In a stmt of a 'do' block: json . pack $ show $ uuid
In the second argument of ‘($)’, namely
‘do { uuid <- nextUUID;
json . pack $ show $ uuid }’
为什么会抛出该错误? 我可以使用一个简单的打印示例轻松创建 uuid,但在 Spock 中,我不明白 ActionCtxT 的作用以及为什么我不能在其中执行 uuid IO。
So I thought, since I am in IO and work with another IO
这就是问题所在,当您在 Spock 中进行路由时,您不在 IO 中。错误消息告诉您您真正处于什么环境:ActionCtxT ctx0 m0
。根据 the docs, that's a monad transformer stack 捆绑效果和状态。
您可以 "lift" 使用 liftIO
将 IO 计算转换为正确的类型。
get ("id") $ do
uuid <- liftIO nextUUID
json . pack $ show $ uuid
根据 Libbys 的有用回答,我刚刚添加了 Maybe UUID
的 Nothing
的捕获。这里是完整的程序:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Web.Spock hiding (head)
import Web.Spock.Config
import Data.UUID.V1
import Data.Pool
import Control.Monad.IO.Class
import Database.PostgreSQL.Simple
import Data.Aeson (Value(Null))
import qualified Network.HTTP.Types.Status as Http
type AppAction a = SpockActionCtx () Connection AppSession AppState a
data AppState = EmptyState
data AppSession = EmptySession
main :: IO ()
main =
do pool<-createPool (connect (ConnectInfo "localhost" 5432 "" "" "envelopes") ) close 1 10 10
spockCfg <- defaultSpockCfg EmptySession (PCPool pool) EmptyState
runSpock 8080 (spock spockCfg app)
app :: SpockM Connection AppSession AppState ()
app = do
get ("json/id") $ do
uuid<-liftIO nextUUID
case uuid of
Nothing -> do
setStatus Http.status500
json Null
Just x -> json $ show x