std::transform
from <algorithm>
header适用于范围,它“使”我们能够使用范围作为它们的函子(在范畴论的意义上(¹))。std::transform
是基于迭代器的,是的,但std::ranges::views::transform
不是,并且它的签名与函数式语言中相应函数的签名非常匹配,以两个参数的不同顺序为模。
当我看到这个问题(并在回答它的过程中)时,我了解到 C++23 引入了std::optional<T>::transform
,它std::optional
也是一个仿函数。
所有这些消息都让我兴奋不已,但我不禁想到函子是通用的,并且对transform
任何函子有一个统一的接口会很好,例如 Haskell 中的情况。
这让我认为std::ranges::views::transform
(它已经是一个对象而不是模板函数)可以作为一个自定义点,STL 不仅可以为范围自定义,还可以为std::optional
STL 中的任何其他仿函数自定义,而程序员可以自定义它用于他们的用户定义的类。
非常相似,C++23 也引入了std::optional<T>::and_then
,这基本上是std::optional
. 我不知道有任何类似的函数为范围实现单子绑定,但 C++20some_range | std::ranges::views::transform(f) | std::ranges::views::join
本质上是some_range
with的单子绑定f
。
这让我觉得可能有一些通用接口,命名它mbind
,可以选择任何类型。STL 会选择加入,例如,std::optional
根据 实现它std::optional<T>::and_then
。
有没有机会,或者有没有计划有一天该语言会支持这种通用性?
我当然可以看到一些问题。今天std::ranges::views::transform(some_optional, some_func)
是无效的,所以一些代码可能通过 SFINAE 依赖它。让它突然工作会破坏代码。
(¹)关于函子这个词,我指的是范畴论中给出的定义(另见this),而不是“已operator()
定义的类的对象”的概念;后者在标准中的任何地方都没有定义,甚至在cppreference中也没有提到,而是使用术语FunctionObject来指代
可以在函数调用运算符左侧使用的对象