我的问题
我指的是一个基本上执行以下操作的函数(模const
,&
完美转发,或任何适当的):
auto constexpr dollar = [](auto f, auto x){ return f(x); }; // Why calling it "dollar"? Keep reading...
这样的功能只能通过 Boost.Hana 表达吗?
为什么我会想到它?
在Haskell中,存在这样一个函数,它被调用($)
($
中缀形式),其定义如下(源码)
($) :: forall r a (b :: TYPE r). (a -> b) -> a -> b
f $ x = f x
并且您可以将第二行简单地写为以下任一
(f $) = f
($) f = f
其中第二种形式显然与(identity function)($)
基本相同id
id :: a -> a
id x = x
只是带有强制第一个参数是函数类型a -> b
和第二个参数类型的签名a
。
事实上,在 Haskell 中申请f
也x
可以通过编写这个来完成
f `id` x
即使用`id`
而不是$
.¹
这和韩有什么关系?
由于 Hana确实提供了一个id
函数,我想知道是否可以使用它(可能与其他东西一起)来定义一个函数应用程序实用程序,而无需在本文顶部手动编写 lambda。
困难的部分
这里的难点在于,当你用f `id` x
Haskell 编写代码时,争论你是传递 1 个参数还是 2 个参数并没有多大意义id
,因为默认情况下所有函数都是柯里化的。
这在 C++ 中是不正确的。例如我可以这样做:
#include <boost/hana/functional/id.hpp>
#include <iostream>
using boost::hana::id;
int main() {
auto plus1 = [](int x){ return x + 1; };
std::cout << id(plus1)(3) << std::endl; // prints 4
}
看起来很像id
被咖喱并且一个接一个地而不是一起给出两个输入,但这不是真的。只是那id(plus1)
正在返回plus1
,它被喂养了3
。我不知道如何获得以下(相当于plus1 `id` 3
或id plus1 3
在 Haskell 中)的工作:
std::cout << id(plus1, 3) << std::endl; // doesn't even compile obviously
谜题的真正由来
在阅读了 To Mock a Mockingbird之后,我想知道:“如何仅使用 Boost.Hana 在 C++ 中实现 Thrush?” (而 Thrush 是boost::hana::flip
函数应用运算符的 ped 版本。)
¹实际上,如果要编写应用程序链,这并不完全相同,因为这两个运算符具有不同的关联性,所以f $ g $ x == f `id` (g `id` x)
,但这与问题无关,我相信。