2

カスタム サーバント ハンドラを作成しました

type ServiceSet = TVar (M.Map String [MicroService])
type LocalHandler = ReaderT ServiceSet IO

しかし、次の関数で 404-not-found ステータス コードをクライアントに応答する方法が見つかりませんでした。

getService :: String -> LocalHandler MicroService
getService sn = do
  tvar <- ask
  ms <- liftIO $ do
    sl <- atomically $ do
      sm <- readTVar tvar
      return $ case M.lookup sn sm of
        Nothing -> []
        Just sl -> sl
    let n = length sl
    i <- randomRIO (0, n - 1)
    return $ if n == 0
      then Nothing
      else Just . head . drop i $ sl
  case ms of
    Nothing -> ??? -- throwError err404
    Just ms' -> return ms'

で 404 ステータス コードを送信する方法は????

4

1 に答える 1

5

ExceptTモナド変換のスタックに追加する必要があります。現時点では、ReaderTスローされるエラーの概念をエンコードする方法はありません。

{-# LANGUAGE DataKinds     #-}
{-# LANGUAGE TypeOperators #-}

module Lib where

import Control.Monad.Except
import Control.Monad.Reader
import Data.Maybe
import Data.Map
import GHC.Conc
import Prelude hiding (lookup)
import Servant.API
import Servant.Server
import System.Random

type API =
  Capture "name" String :> Get '[JSON] Int

type World =
  TVar (Map String [Int])

type Effects =
  ExceptT ServantErr (ReaderT World IO)

server :: World -> Server API
server world =
  enter (Nat transform) get
  where
    transform :: Effects a -> ExceptT ServantErr IO a
    transform (ExceptT foo) =
      ExceptT $ runReaderT foo world

get :: String -> Effects Int
get sn = do
  tvar <- ask
  ms <- liftIO $ do
    sl <- atomically $ do
      sm <- readTVar tvar
      return (fromMaybe [] (lookup sn sm))
    let n = length sl
    i <- randomRIO (0, n - 1)
    return $ if n == 0
      then Nothing
      else Just . head . drop i $ sl
  case ms of
    Nothing ->
      throwError err404
    Just ms' ->
      return ms'

ExceptT ServantErr . ReaderT (TVar ...)次にthrowError err404、どのサーヴァントがキャッチして HTTP 404 を返すために使用することができます。自然な変換はExceptT ServantErr . ReaderT (TVar ...) :~> ExceptT ServantErr、リーダー効果を放電するためにラップを解除して再ラップする必要があります。全体として、それほど多くのコードはありません。

于 2016-07-04T19:40:26.073 に答える