Maa*_*mon 4 functional-programming scala http4s
我很难理解为什么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]
}
Run Code Online (Sandbox Code Playgroud)
尤其
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类似的方式
Resource 是一个 IO 操作,它获取 a 类型的某些资源,并返回释放该资源的 IO () 类型的终结器。您可以将 a 视为句柄,但它实际上可以是任何可以获取或释放的东西,例如 Socket 或 AMQP 连接。
我们能否对什么是响应及其作用有一个概念性定义,这确实需要它在特定效果类型上进行参数化?
让我们看看 的定义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]]
Run Code Online (Sandbox Code Playgroud)
Kleisli本质上是一个有效函数的包装A => F[B]::
final case class Kleisli[F[_], -A, B](run: A => F[B])
Run Code Online (Sandbox Code Playgroud)
如果我们在这里开发类型俄罗斯方块,我们会看到 Http 的实际类型签名是:
Request[G] => F[Response[G]]
Run Code Online (Sandbox Code Playgroud)
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] {
Run Code Online (Sandbox Code Playgroud)
您可以看到 theF用于 the EntityBody[F],它本身就是 a 的类型别名Stream[F, Byte],用于延迟消耗 Effect 中的输入/输出流F。
具体来说HttpRoutes[F],两个类型参数实际上是相同的:
type HttpRoutes[F[_]] = Http[OptionT[F, *], F]
Run Code Online (Sandbox Code Playgroud)
这确实是:
Request[F] => F[Option[Response[[F]]]
Run Code Online (Sandbox Code Playgroud)
因此,我们F[Response[F]]到处都看到而不是有一个单独的类型参数体。
总而言之,外部F输入F[Response[G]]用于捕获生成响应可能是有效操作的事实。这就是为什么F通常是某种 IO 类型(cats-effectIO等ZIO[R, E, A]),并且请求/响应中的内部G用于对在给定效果中生成字节的流进行建模。
| 归档时间: |
|
| 查看次数: |
420 次 |
| 最近记录: |