Haskell Spock IO в GET Route Ошибка ActionCtxT
Я пытаюсь вернуть uuid в определении маршрута для веб-приложения ( Spock Webserver).
Маршрут довольно просто определить
get("PATH") $ do
text "Hello World"
Теперь я пытаюсь вернуть UUID через nextRandom
из модуля Data.UUID.V1. Функция возвращает 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.
2 ответа
Вот я и подумал, так как я в IO и работаю с другим IO
Вот в чем проблема, когда вы маршрутизируете в Споке, вы не в IO. Сообщение об ошибке говорит вам, в каком контексте вы действительно находитесь: ActionCtxT ctx0 m0
, Согласно документации, это монадный стек преобразователя, который объединяет эффекты и состояние.
Вы можете "поднять" вычисление ввода-вывода в нужный тип, используя liftIO
,
get ("id") $ do
uuid <- liftIO nextUUID
json . pack $ show $ uuid
Основываясь на полезном ответе Libbys, я только что добавил улов для Nothing
из Maybe 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