0

我尝试在 Web 应用程序( Spock Webserver)的路由定义中返回一个 uuid 。

路线很容易定义

get("PATH") $ do
 text "Hello World"

现在我尝试nextRandomData.UUID.V1模块返回一个 uuid。该函数返回一个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。

4

2 回答 2

2

所以我想,因为我在 IO 并与另一个 IO 一起工作

这就是问题所在,当你在 Spock 中路由时,你不在 IO 中。错误消息告诉您您真正所处的上下文:ActionCtxT ctx0 m0. 根据文档,这是一个捆绑效果和状态的单子转换器堆栈。

您可以使用liftIO.

get ("id") $ do
    uuid <- liftIO nextUUID
    json . pack $ show $ uuid
于 2017-02-25T19:42:08.197 回答
0

基于 Libbys 有用的答案,我刚刚添加NothingMaybe UUID. 这里是完整的程序:

{-# 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
于 2017-02-28T21:18:02.943 回答