std::transform来自<algorithm> header适用于范围,它“使”我们能够使用范围作为它们的函子(从范畴论的意义上来说(¹)). std::transform
是基于迭代器的,是的,但是std::ranges::views::transform不是,它的签名与函数语言中相应函数的签名非常匹配(对两个参数的不同顺序取模,但这没什么大不了的)。
当我看到这个问题(并且在这个过程中回答它),我了解到C++23引入了std::optional<T>::transform,这使得std::optional
也是一个函子。
所有这些消息确实让我兴奋,但我不禁想到函子是通用的,如果有一个统一的接口就好了transform
任何函子,例如 Haskell 中的情况。
这让我认为一个类似于std::ranges::views::transform
(使用不同的名称并不是暗示ranges
)可以做成定制点STL 不仅可以针对范围进行定制,还可以针对std::optional
对于 STL 中的任何其他仿函数,而程序员可以为其用户定义的类自定义它。
类似地,C++23 也引入了std::optional<T>::and_then,这基本上是一元绑定std::optional
。我不知道有任何类似的函数可以实现范围的单子绑定,但是 C++20 的some_range | std::ranges::views::transform(f) | std::ranges::views::join
本质上是一元绑定some_range
with f
.
这让我觉得可能有一些通用接口,命名它mbind
,可以选择任何类型。 STL 将选择加入std::optional
通过实施它std::optional<T>::and_then
, 例如。
该语言是否有机会或有计划有一天支持这种通用性?
I can certainly see some problems. Today std::ranges::views::transform(some_optional, some_func)
is invalid, so some code might be relying on that via SFINAE. Making it suddenly work would break the code. No quite, breaking code that relies on SFINAE-based detection of invalid code is ok.
(1) 关于这个词functor,我指的是范畴论中给出的定义(另见this),而不是“具有以下特征的类的对象”的概念operator()
定义”;后者在标准中没有定义甚至没有提到参考参数,它使用术语函数对象参考
可以在函数调用运算符左侧使用的对象