需要澄清混淆 Http4s 消息类型 `Response[F]` / `Request[F]`
Need clarification for confusing Http4s Message Type `Response[F]` / `Request[F]`
我很难理解为什么 Request 和 Response 在 F 中被参数化。
采用类似的东西是猫效应数据类型资源。
来自文档
https://typelevel.org/cats-effect/docs/std/resource
我们找到如下定义
object Resource {
def make[F[_], A](acquire: F[A])(release: A => F[Unit]): Resource[F, A]
def eval[F[_], A](fa: F[A]): Resource[F, A]
}
abstract class Resource[F, A] {
def use[B](f: A => F[B]): F[B]
}
特别是
def use[B](f: A => F[B]): F[B]
说清楚了为什么Resource在F里参数化。
鉴于文档中没有任何解释 Response[F] 的内容(请注意,我非常理解为什么 F[Response],它是我不理解的内部 F),我查看了一下代码 https://github.com/http4s/http4s/blob/main/core/src/main/scala/org/http4s/Message.scala
除非我看得不够仔细,否则我找不到任何可以证明效果类型存在的理由。
谁能解释一下里面的F参数。
与 https://www.haskellforall.com/2013/06/the-resource-applicative.html
类似
A Resource is an IO action which acquires some resource of type a and
also returns a finalizer of type IO () that releases the resource. You
can think of the a as a Handle, but it can really be anything which
can be acquired or released, like a Socket or AMQP Connection.
我们能否对什么是响应及其作用有一个概念性定义,这确实需要根据特定效果类型对其进行参数化?
让我们看看 Http[F, G]
的定义,这是 http4s
的核心:
/** A kleisli with a [[Request]] input and a [[Response]] output. This type
* is useful for writing middleware that are polymorphic over the return
* type F.
*
* @tparam F the effect type in which the [[Response]] is returned
* @tparam G the effect type of the [[Request]] and [[Response]] bodies
*/
type Http[F[_], G[_]] = Kleisli[F, Request[G], Response[G]]
Kleisli
本质上是一个有效函数的包装器:A => F[B]
:
final case class Kleisli[F[_], -A, B](run: A => F[B])
如果我们在这里开发类型 tetris,我们会看到 Http 的实际类型签名是:
Request[G] => F[Response[G]]
现在,Request
和 Response
在 G
中参数化的原因是它们可能包含主体。我们从两个定义中看到这一点:
final class Request[F[_]](
val method: Method = Method.GET,
val uri: Uri = Uri(path = "/"),
val httpVersion: HttpVersion = HttpVersion.`HTTP/1.1`,
val headers: Headers = Headers.empty,
val body: EntityBody[F] = EmptyBody,
val attributes: Vault = Vault.empty
final case class Response[F[_]](
status: Status = Status.Ok,
httpVersion: HttpVersion = HttpVersion.`HTTP/1.1`,
headers: Headers = Headers.empty,
body: EntityBody[F] = EmptyBody,
attributes: Vault = Vault.empty)
extends Message[F] {
您可以看到 F
用于 EntityBody[F]
,它本身是 Stream[F, Byte]
的类型别名,用于在效果 F
.
针对HttpRoutes[F]
的情况,两个类型参数实际上是相同的:
type HttpRoutes[F[_]] = Http[OptionT[F, *], F]
这是真的:
Request[F] => F[Option[Response[[F]]]
因此我们到处都看到 F[Response[F]]
而不是单独的类型参数体。
综上所述,F[Response[G]]
中的外部 F
用于捕获生成响应可能是有效操作这一事实。这就是为什么 F
通常是某种 IO 类型(cats-effect IO
、ZIO[R, E, A]
等),而 request/response 中的内部 G
用于模拟在给定效果中产生字节的流。
我很难理解为什么 Request 和 Response 在 F 中被参数化。
采用类似的东西是猫效应数据类型资源。
来自文档
https://typelevel.org/cats-effect/docs/std/resource
我们找到如下定义
object Resource {
def make[F[_], A](acquire: F[A])(release: A => F[Unit]): Resource[F, A]
def eval[F[_], A](fa: F[A]): Resource[F, A]
}
abstract class Resource[F, A] {
def use[B](f: A => F[B]): F[B]
}
特别是
def use[B](f: A => F[B]): F[B]
说清楚了为什么Resource在F里参数化。
鉴于文档中没有任何解释 Response[F] 的内容(请注意,我非常理解为什么 F[Response],它是我不理解的内部 F),我查看了一下代码 https://github.com/http4s/http4s/blob/main/core/src/main/scala/org/http4s/Message.scala
除非我看得不够仔细,否则我找不到任何可以证明效果类型存在的理由。
谁能解释一下里面的F参数。
与 https://www.haskellforall.com/2013/06/the-resource-applicative.html
类似A Resource is an IO action which acquires some resource of type a and also returns a finalizer of type IO () that releases the resource. You can think of the a as a Handle, but it can really be anything which can be acquired or released, like a Socket or AMQP Connection.
我们能否对什么是响应及其作用有一个概念性定义,这确实需要根据特定效果类型对其进行参数化?
让我们看看 Http[F, G]
的定义,这是 http4s
的核心:
/** A kleisli with a [[Request]] input and a [[Response]] output. This type
* is useful for writing middleware that are polymorphic over the return
* type F.
*
* @tparam F the effect type in which the [[Response]] is returned
* @tparam G the effect type of the [[Request]] and [[Response]] bodies
*/
type Http[F[_], G[_]] = Kleisli[F, Request[G], Response[G]]
Kleisli
本质上是一个有效函数的包装器:A => F[B]
:
final case class Kleisli[F[_], -A, B](run: A => F[B])
如果我们在这里开发类型 tetris,我们会看到 Http 的实际类型签名是:
Request[G] => F[Response[G]]
现在,Request
和 Response
在 G
中参数化的原因是它们可能包含主体。我们从两个定义中看到这一点:
final class Request[F[_]](
val method: Method = Method.GET,
val uri: Uri = Uri(path = "/"),
val httpVersion: HttpVersion = HttpVersion.`HTTP/1.1`,
val headers: Headers = Headers.empty,
val body: EntityBody[F] = EmptyBody,
val attributes: Vault = Vault.empty
final case class Response[F[_]](
status: Status = Status.Ok,
httpVersion: HttpVersion = HttpVersion.`HTTP/1.1`,
headers: Headers = Headers.empty,
body: EntityBody[F] = EmptyBody,
attributes: Vault = Vault.empty)
extends Message[F] {
您可以看到 F
用于 EntityBody[F]
,它本身是 Stream[F, Byte]
的类型别名,用于在效果 F
.
针对HttpRoutes[F]
的情况,两个类型参数实际上是相同的:
type HttpRoutes[F[_]] = Http[OptionT[F, *], F]
这是真的:
Request[F] => F[Option[Response[[F]]]
因此我们到处都看到 F[Response[F]]
而不是单独的类型参数体。
综上所述,F[Response[G]]
中的外部 F
用于捕获生成响应可能是有效操作这一事实。这就是为什么 F
通常是某种 IO 类型(cats-effect IO
、ZIO[R, E, A]
等),而 request/response 中的内部 G
用于模拟在给定效果中产生字节的流。