Scala “F[某物[F]]”背后的意图是什么?

Scala “F[某物[F]]”背后的意图是什么?,scala,scala-cats,cats-effect,Scala,Scala Cats,Cats Effect,我看到周围有很多F[Request[F]],F[Monitor[F]]和F[Something[F]]。虽然我了解如何处理这个问题的机制,但我无法直观地理解为什么某些效果(F)会像这样出现(既环绕某物,又出现在该某物)内部)。洞察?F[\uu]只是一个抽象概念。它可以是具有*->*类型的列表或其他内容的IO。您可以定义通用函数的主要思想。一个很好的例子是函子类型类和该类中的映射函数。 所以在你的代码中,你可以说你的F是一个函子(F[]:函子),在它允许你使用映射函数之后 一个简单的HTTP服务器

我看到周围有很多
F[Request[F]]
F[Monitor[F]]
F[Something[F]]
。虽然我了解如何处理这个问题的机制,但我无法直观地理解为什么某些效果(
F
)会像这样出现(既环绕
某物
,又出现在该
某物
)内部)。洞察?

F[\uu]只是一个抽象概念。它可以是具有*->*类型的列表或其他内容的IO。您可以定义通用函数的主要思想。一个很好的例子是函子类型类和该类中的映射函数。
所以在你的代码中,你可以说你的F是一个函子(F[]:函子),在它允许你使用映射函数之后

一个简单的HTTP服务器可以用以下函数表示: 请求=>响应

然而,我们通常需要执行有效的操作,例如从数据库检索数据或调用外部服务。我们对此类情况的定义如下: 请求=>F[响应]

http4s对路由(端点)有自己的抽象,称为HttpRoutes[F],它是文档中提到的Kleisli[OptionT[F,?],Request,Response]的类型别名

正如我们从cats文档中了解到的,Kleisli只是返回一元值的函数的组合,如选项[a]、[L,R]等

函数最有用的特性之一是它们的组合。也就是说,给定一个函数a=>B和一个函数B=>C,我们可以组合它们来创建一个新函数a=>C

在本例中,http4s的Kleislei接受请求并返回F[Response],只需请求=>F[Response]。F是一种效果类型

对上述请求和响应类型稍作修改后,我们得到以下结果:

type HttpRoutes[F] = Kleisli[OptionT[F, *], Request[F], Response[F]]
HttpRoutes[F]被声明为一系列简单的case语句。每个case语句都尝试匹配传入请求[F],并有选择地从传入请求[F]中提取。与第一个匹配案例关联的代码用于生成F[响应[F]]

最简单的case语句匹配所有请求,而不提取任何内容。请求的右侧必须返回F[响应[F]]

我们可以在这里看到F[Response[F]]的简单演示

scala> val getRoot = Request[IO](Method.GET, uri"/")
getRoot: org.http4s.Request[cats.effect.IO] = Request(method=GET, uri=/, headers=Headers())

scala> val io = service.orNotFound.run(getRoot)
io: cats.effect.IO[org.http4s.Response[cats.effect.IO]] = <function1>
  • Gabriel Volpe的Scala实用FP

  • 问题不是关于一般意义上的
    F[\u]
    意味着什么(你的答案是关于什么的)。但是关于
    F[X[F]]
    的直觉是什么呢
    F
    出现在
    X
    的周围和内部。哦,明白了。有时会发生这种情况。例如,在我的代码中,F[X[F]]出现在模块创建中。内部F表示模块X的效果类型,外部F表示构造效果类型。没有必要在内部和外部使用相同的效果类型,您可以使用F[X[G]],但为了简化,F和G被认为是相同的,因为事实上,它在现实生活中是一个IO。我认为最好添加一份关于为什么使用X[F]的文档。F[X]解释得很好。例如,资源数据类型在it定义
    def use[B](f:A=>f[B]):f[B]
    中很好地解释了它。但不清楚的是,一个反应到底应该做什么,才有F效应。响应需要执行哪些操作,这些操作会产生副作用,因此会表示为外部操作描述。这就是文档和其他地方缺少的空白。资源在某种程度上被定义为一个IO操作,…一个在流程中获取、发布和使用的操作。但是什么是概念性的反应,比如说需要做F的东西?该概念部分在文档中找不到。简单回答,
    某物将产生副作用,因此它是一种参数化的效果类型。因此,
    Something[F]
    。然后,可能
    某物的创建也是一个副作用(主要是因为某物是一个共享的可变状态),因此它的创建也必须包含一些影响。为了简单起见,我们说这两种效果是相同的。如果你对
    F[Something[F]]
    的起源感兴趣,你应该阅读递归方案,
    Free
    /
    Cofree
    ,tagless final。我非常喜欢这篇文章。另外(我对这些概念也很陌生)-效果是
    F
    ,因此您通过
    响应[F]
    产生效果。这是
    F[Response[F]]
    Response[T[]]
    需要
    F
    来实现抽象类和接口,这些抽象类和接口也需要底层类型
    F
    ,以确保在运行时实现和生成的效果类型(
    Future
    Task
    IO
    )是一致的。我认为这是一种安全的东西。与响应[F]一样,它对响应[F]的含义是什么?它在内部做什么?我已经为此发布了一个具体的问题
    scala> val response = io.unsafeRunSync
    response: org.http4s.Response[cats.effect.IO] = Response(status=200, headers=Headers())