scala - 高级 C[_] ~> D[_] 的多态函数真的是自然变换吗?
问题描述
这是一个关于术语的问题,在 scala shapeless 库中我发现了以下评论:
/**
* Base trait for natural transformations.
*
* @author Miles Sabin
*/
trait ~>[F[_], G[_]] extends Poly1 {
这定义F[_] ~> G[_]
为自然转换。但我不确定它是否在滥用术语,在维基百科中:
https://en.wikipedia.org/wiki/Natural_transformation
它被定义为函子之间的结构保持态射。例如对于函数的底层函子Int => String
:
v: Int => v.toString
自然转换可以将其转换为另一个仿函数,例如List[Int] => List[String]
orSet[Int] => Set[String]
等。这似乎表明 scala 中最接近自然转换的对象实际上是CanBuildFrom
集合库中的类型类:
trait CanBuildFrom[-From, -Elem, +To]
...
object Example extends CanBuildFrom[List[Int], Int, List[String]]
其中(在柯里化之后)是从一个函子F[_]: Elem => From
到另一个函子的态射G[_]: Elem => To
。据我所知,由 定义的 Poly1~>
不具备这种能力(采用任何函子 X => Y 并产生 List[X] => List[Y]),那么为什么将其称为自然变换呢?
UPDATE 1,我想我可能需要澄清一下。一些库(如猫)中的函子定义仅包含类型构造函数,例如:
T => List[T]
但是根据数学定义,仿函数应该类似于 lambda 类型,例如以下也应该是仿函数
T => String
T => List[String] // in that CanBuildFrom example
我的问题是,从这个意义上说,类型类CanBuildFrom
应该是自然转换。然而,在无形中,除非我使用临时多态性(Poly1 主体中的多个隐含),否则我无法定义它。那么这究竟~>
意味着什么呢?
非常感谢您的意见
解决方案
范畴论在编程语言中并不总是可以 1-1 实现。例如函子。当你有F
允许翻译A => B
成F[A] => F[B]
它的数据结构时,它就是一个函子。但是,如果您使用协方差F[+A]
,这A <: B
意味着F[A] <: F[B]
您也有一个函子,但在类型级别上。
没有一个结构可以让您描述仿函数的所有用法。从理论上讲,如果你有一些F[A] => F[B]
可以翻译成G[A] => G[B]
的东西,并且你可以组成的所有东西都F
应该有一个对应的组成 in G
,那么你就有了一个函子。但是你不能F => G
为所有东西生成这样的函数。如果你从 开始,你可以很容易地生成这样的映射Id
,所以仅仅因为方便,所有描述函子的类型类只描述一个映射,它从“forever”由泛型处理的地方开始Id[A]
。这只是一些价值层面的函子——还有类型上的函子。或者在任何其他多重图上,例如,您可以定义枚举中某些值之间的转换F[A]
A
E1
然后对另一个 enum 做同样的事情E2
,如果一个是另一个的子图并且你提供了一个映射(一些受约束的(E1, E1)
=> (E2, E2)
) - 这也是一个仿函数。你不会只用一个通用的[A]
. 如果你专门为这些枚举实现函子,Functor
接口的通用性和可组合性不会有任何好处。它只是一个恰好描述函子的函数,那又如何呢?
这会影响自然转换。实际上,我们在 Cats 或类似中描述的唯一自然变换是Id[A] => F[A]
和之间的自然变换Id[A] => G[A]
。它们很容易实现,因为您基本上是F[A] => G[A]
在Id[A] => F[A]
获取Id[A] => G[A]
. 在一般情况下并不容易。
这些仍然是函子和自然转换。只是为了我们的实际目的,我们只考虑函子和 NT,Id
因为我们可以经常、轻松且廉价地创建它们。泛型/参数类型免费为您提供映射A
=> F[A]
,A
我们只是在此基础上构建。您可以开始使用~>
for 仿函数,然后创建一个处理此类仿函数(自然转换)的仿函数……但您很快会发现,像(A ~> B) ~> (C ~> D)
while 模型这样的好主意,使用起来也非常不切实际。数学中的许多概念也是如此。我们没有完美地建模它们,而只是使用在特定上下文中对我们有用的特定专业化。
推荐阅读
- reactjs - why is firebase serve working fine but not firebase deploy?
- java - 通过单链表插入实现的优先队列
- azure - Azure Batch 和连接到 Key Vault
- ios - WKWebView InAppBrowser 持久存储
- reactjs - 反应渲染多个
从 Material-UI 不使用 map() - php - 使用 cURL 将 Pdf 文件上传到另一个网站
- mongodb - Mongodb 指定类型“字符串”也返回“数组”字段
- image-processing - 如何标记图像的对象
- javascript - 编写javascript来检测速度
- javascript - Jquery发送Ajax并且没有等待发送其他ajax的响应