gpt4 book ai didi

haskell - 使用 Servant 根据 `Maybe` 的内容以 200 或 404 响应请求

转载 作者:行者123 更新时间:2023-12-01 16:00:41 24 4
gpt4 key购买 nike

我目前正在尝试使用 servant 实现一个简单的 Web 服务器。目前,我有一个 IO (Maybe String) 我想通过 GET 端点公开(这可能是一个数据库查找,可能返回也可能不返回结果,因此 IO可能)。如果 Maybe 包含一个值,则响应应包含此值以及 200 OK 响应状态。如果 MaybeNothing,则应返回 404 Not Found

到目前为止,我一直在关注 the tutorial ,其中还描述了使用 throwError 处理错误。但是,我还没有设法让它编译。我有以下代码:

type MaybeAPI = "maybe" :> Get '[ JSON] String

server :: Server MaybeAPI
server = stringHandler

maybeAPI :: Proxy MaybeAPI
maybeAPI = Proxy

app :: Application
app = serve maybeAPI server

stringHandler :: Handler String
stringHandler = liftIO $ fmap (\s -> (fromMaybe (throwError err404) s)) ioMaybeString

ioMaybeString :: IO (Maybe String)
ioMaybeString = return $ Just "foo"

runServer :: IO ()
runServer = run 8081 app

我知道这可能比它需要的更冗长,但我想它一旦开始工作就可以简化。问题是 stringHandler,编译失败并显示:

No instance for (MonadError ServerError []) arising from a use of ‘throwError’

所以我的问题是:这是在 Servant 中实现这样一个端点的方式吗?如果是这样,我该如何解决实现问题?我的 Haskell 知识相当有限,而且我以前从未使用过 throwError,所以我很可能在这里遗漏了一些东西。感谢您的帮助!

最佳答案

正如我在评论中提到的,问题在于违规行:

stringHandler :: Handler String
stringHandler = liftIO $ fmap (\s -> (fromMaybe (throwError err404) s)) ioMaybeString

s 是一个 Maybe String,所以要将它用作 fromMaybe 的第二个参数,第一个参数必须是一个 String - throwError 永远不会生成字符串。

虽然您谈到您的代码可能过于冗长并且您稍后会考虑简化它,但我认为这里的部分问题是在这个特定的处理程序中您试图过于简洁。让我们试着用一种更基本的、伪命令式的风格来写它。由于 Handler 是一个 monad,我们可以将其写在 do block 中,该 block 检查 s 的值并采取适当的操作:

stringHandler :: Handler String
stringHandler = do
s <- liftIO ioMaybeString
case s of
Just str -> return str
Nothing -> throwError err404

请注意,throwError 可以生成类型为 Handler a 的任何类型的值,在本例中为 String。而且我们必须在 ioMaybeString 上使用 liftIO 将其提升到 Handler monad 中,否则不会进行类型检查。

我能理解为什么您可能认为 fromMaybe 很适合这里,但从根本上说它不是 - 原因是它是一个“纯”函数,不涉及 IO所有,而当你谈论抛出服务器错误时,你绝对不可避免地在做 IO。这些东西基本上不能混合在一个函数中。 (这也使得 fmap 不合适 - 它当然可以用于“提升”纯计算以处理 IO 操作,但在这里,正如我所说,你需要的计算根本不是纯。)

如果你想让上面的 stringHandler 函数更简洁,虽然我不认为这是一个真正的改进,你仍然可以显式地使用 >>= do block 的代码,而不会使代码太难读:

stringHandler = liftIO ioMaybeString >>= f
where f (Just str) = return str
f Nothing = throwError err404

关于haskell - 使用 Servant 根据 `Maybe` 的内容以 200 或 404 响应请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59805491/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com