haskell 如何在原始服务处理程序中使用IO?

pbpqsu0x  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(140)

我使用servant 0.19,所以没有RawM类型。我有个负责人

hnd :: Something -> ServerT Raw Handler
hnd Something {..} = do
  -- p <- readIORef somePath -- COULDN'T MATCH TYPE "IO b0" WITH "Tagged Handler Application"
  let stSet = defaultFileServerSettings "a/b/c"
  serveDirectoryWith stSet

字符串
它被描述为API的类型::<|> "some" :> Raw
我想在我的hnd处理程序中执行IO操作。如何使用这个servant版本(没有RawM)?另外,如果您也使用RawM来展示它,我将不胜感激(尽管由于使用的是0.19版本,所以这并不重要)。

kq4fsx7k

kq4fsx7k1#

简短的回答。试试看:

hnd :: Something -> ServerT Raw Handler
hnd Something{..} = Tagged $ \req resp -> do
  p <- readIORef somePath
  let stSet = defaultFileServerSettings p
  staticApp stSet req resp

字符串
较长的答案是,ServerT是与HasServer类型类相关联的类型家族,该类型类将API表达式Map到Handler monad的转换,以实现API :>:<|>组合子以及各个端点。对于“普通”端点,如Get,它将类型ServerT (Get ...) HandlerMap到普通的旧Handler
为了实现Raw,将ServerT Raw HandlerMap到Tagged Handler Application。这只是一个阿威Application,其类型为Tagged,带有Handler单子。
Servant提供的wrappers,比如serveDirectoryWith,实际上只是已经是Tagged的阿威Application

serveDirectoryWith :: StaticSettings -> ServerT Raw m
serveDirectoryWith = Tagged . staticApp


其中,staticApp是为wai-app-static包中的Application提供服务的基础静态文件。
因此,这意味着简化的处理程序:

hnd :: Something -> ServerT Raw Handler
hnd _ = serveDirectoryWith "a/b/c"


相当于:

hnd _ = Tagged (staticApp "a/b/c")


假设一个Application实际上是一个Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived,这是相同的:

hnd _ = Tagged (\req resp -> staticApp "a/b/c" req resp)


或者:

hnd Something{..} = Tagged $ \req resp -> do
  staticApp "a/b/c" req resp


其中do-块在普通的旧IO monad中运行。在这种形式下,现在可以做“正常”的IO工作,这就是我如何得出上面的简短答案。
0.20版的RawM在这里没有给你带来多少好处。它将ServantT RawM HandlerMap到应用程序的修改版本:

Request -> (Response -> IO ResponseReceived) -> Handler ResponseReceived
                                                ^^^^^^^
                                                instead of IO


这增加了执行除X1 M27 N1 X之外的X1 M26 N1 X动作的能力,即,用信号通知特定的X1 M28 N1 X。如果你有一个自定义的HandlerT,它可能会更有用。但是,这并不会使编写hnd变得更容易。

相关问题