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
Другие вопросы по тегам