![](/img/trans.png)
[英]How std::transform is initializing the functor with a specific value?
[英]Could std::foo::transform one day support any functor?
<algorithm>
header 中的std::transform
適用於范圍,它“使”我們能夠使用范圍作為它們的函子(在范疇論的意義上(¹))。 std::transform
是基於迭代器的,是的,但std::ranges::views::transform
不是,它的簽名與函數式語言中相應函數的簽名非常匹配,以兩個 arguments 的不同順序為模。
當我看到這個問題(並在回答它的過程中)時,我了解到 C++23 引入了std::optional<T>::transform
,這使得std::optional
也成為一個仿函數。
所有這些消息確實讓我興奮,但我不禁認為函子是通用的,如果有一個統一的接口來transform
任何函子,那就太好了,例如 Haskell 中的情況。
這讓我認為 object 類似於std::ranges::views::transform
(具有不同的名稱不暗示ranges
)可以作為定制點,STL 不僅可以為范圍定制,還可以為std::optional
和 STL 中的任何其他仿函數,而程序員可以為他們的用戶定義的類定制它。
非常相似,C++23 也引入了std::optional<T>::and_then
,它基本上是std::optional
的一元綁定。 我不知道有任何類似的 function 實現了范圍的單子綁定,但是 C++20 的some_range | std::ranges::views::transform(f) | std::ranges::views::join
some_range | std::ranges::views::transform(f) | std::ranges::views::join
some_range | std::ranges::views::transform(f) | std::ranges::views::join
本質上是some_range
與f
的一元綁定。
這讓我覺得可能有一些通用接口,命名為mbind
,可以選擇任何類型。 例如,STL 將通過std::optional<T>::and_then
實現它來選擇std::optional
::optional 。
有沒有機會,或者有沒有計划有一天該語言會支持這種通用性?
我當然可以看到一些問題。 今天std::ranges::views::transform(some_optional, some_func)
是無效的,所以一些代碼可能通過 SFINAE 依賴它。 讓它突然工作會破壞代碼。
(¹)關於函子這個詞,我指的是范疇論中給出的定義(另請參見this ),而不是“定義了operator()
的 class 的對象”的概念; 后者在標准中的任何地方都沒有定義,甚至在cppreference中也沒有提到,而是使用術語FunctionObject來指代
可以在 function 呼叫運算符左側使用的 object
我不知道有任何類似的 function 實現了范圍的單子綁定,但是 C++20 的
some_range | std::ranges::views::transform(f) | std::ranges::views::join
some_range | std::ranges::views::transform(f) | std::ranges::views::join
some_range | std::ranges::views::transform(f) | std::ranges::views::join
本質上是some_range
與f
的一元綁定。
ranges::views::for_each
是范圍( read )的一元綁定,我更喜歡它而不是views::transform | views::join
views::transform | views::join
由於(過去?)range-v3 的復雜性/打字問題。
至於你是否會得到 Functor 和 Monad 的通用接口。 我對此表示懷疑,除非這種通用性對編寫模板的庫作者有用。 std::expiremental::future
也是一元的(我想 Executors 也是),因此可以在這三種類型上編寫諸如foldM
類的通用算法。 我認為 Erik Niebler 已經用 range-v3 表明,可以編寫一個 Functor/Monad 庫,但要以手動編碼每個 pipe 運算符為代價,即
#include <fp_extremist.hpp>
template <typename M> requires Monad<M>
auto func(M m)
{
return m
| fp::extremist::fmap([](auto a) { return ...; })
| fp::extremist::mbind([](auto b) { return ...; })
;
}
我認為實際上可能的是,我們將獲得 UFCS 和|>
運算符,因此我們可以獲得可invocable |> east
語法的好處以及 pipe 到算法的能力。 來自巴里的博客:
它不起作用,因為雖然范圍適配器是可管道的,但算法不是。 ...
也就是說,x |> f 仍然像以前一樣評估為 f(x)……但 x |> f(y) 評估為 f(x, y)。
PS 在 c++: <typename T> struct
that provides transform
中給出 Functor 的定義並不難。 PSS 也不清楚如何處理應用程序。 你想寫類似的東西
auto out = std::optional{1}
, std::optional{1}
| fp::extremist::app([](auto a, auto b){...})
;
並將其轉換為
auto out = [](auto a){ return [](auto b) {...}; }
| fp::extremist::fmap(std::optional{1})
| fp::extremist::app(std::optional{1})
;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.