我正在尝试建立理解一系列嵌入式匿名表达式的最佳方法,例如:
(\f -> (\g -> (\x -> f (g x) ) ) )
在Haskell。对于简单的表达式我没有太多麻烦,例如:
(\x -> x + 1)
其中声明该函数采用Number并返回一个数字:
Num a => a -> a
但是当事情像这样被嵌入时我会迷失方向。我试图理解它是匿名函数立即将参数从f
传递到g
到x
,然后我应该开始编写输入,因为它是使用变量的地方。但我已经尝试合理化了四五种不同的解释,并且我一直在内心函数中看起来像一个递归函数调用。
可以更容易地找出这个问题的输入吗?
答案 0 :(得分:4)
这只是一个讨论的例子。 Haskell为此提供了语法糖:
\f g x -> f (g x)
在任何一种情况下,将函数应用于参数foo1
都会返回函数
\g x -> foo1 (g x)
将此应用于函数foo2
会返回另一个函数
\x -> foo1 (foo2 x)
如果应用于另一个参数bar
将返回由foo1 (foo2 bar)
计算的值。
在像Python这样的语言中,它看起来像
compose1 = lambda f: lambda g: lambda x: f(g(x))
由于Python函数默认不是curry,因此这是一个独特的
来自compose2 = lambda f,g,h: f(g(x))
的功能。两者的区别
就是你如何使用它们。
compose1(foo1)(foo2)(bar)
compose2(foo1, foo2, bar)
使用def
语句撰写,compose1
看起来像
def compose1(f):
def _1(g):
def _2(x):
return f(g(x))
return _2
return _1
答案 1 :(得分:3)
你不需要过度思考这个问题。 (\f -> (\g -> (\x -> f (g x) ) ) )
只是参数f
的一个函数,其中某些结果 ...恰好是一个函数,但它原则上与一个函数没什么不同结果为数字的函数。它只是一些黑盒......
\f -> ██
现在,当您将此lambda实际应用于某个f
时,您可以访问blackbox。例如,我可以将其应用于sqrt
函数:
(\f -> ██) sqrt
≡ ██
= \g -> ██₂
好的,另一个产生一些黑盒子的lambda。让我们将其应用于(^2)
(\g -> ██₂) (^2)
≡ ██₂
= \x -> ██₃
现在blackbox并不是那么黑暗:它只是f (g x)
,其中f
,g
和x
是我们'已经申请:
(\f -> (\g -> (\x -> f (g x) ) ) ) sqrt (^2)
≡ \x -> sqrt (x^2)
当然,这只是一个例子。通常,你的大lambda需要两个函数,并为你提供两个函数的组合。当然这更好地写成
\f g x -> f $ g x
或实际上只是.
答案 2 :(得分:1)
将整个lambda函数想象成一个黑盒子。从签名我们知道有三个箭头“ - >”分开每个论点。这告诉你这个黑盒子收到3个实际参数:f g x。它将f应用于将g应用于x的结果。通过查看其命名函数等价来更容易理解。
compose f g x = f (g x)
compose' f g = \x -> f (g x)