了解 Haskell 中的嵌入式匿名函数?
Understanding embedded anonymous functions in Haskell?
我正在尝试建立理解一系列嵌入式匿名表达式的最佳方法,例如:
(\f -> (\g -> (\x -> f (g x) ) ) )
在Haskell。我对更简单的表达式没有太多麻烦,例如:
(\x -> x + 1)
其中指出该函数接受一个数字和 returns 一个数字:
Num a => a -> a
但是当事情像这样嵌入时,我就迷路了。我试图理解它是匿名函数立即将参数从 f
传递到 g
再到 x
,然后我应该开始编写类型,因为它是使用变量的地方.但我已经尝试合理化可能四五个不同的解释,并且我一直在关注最内层函数中看起来像递归函数调用的东西。
这个问题的类型可以用更简单的方式解决吗?
这只是柯里化的一个例子。 Haskell 为此提供语法糖:
\f g x -> f (g x)
在任何一种情况下,将函数应用于参数 foo1
return 函数
\g x -> foo1 (g x)
将其应用于一个函数 foo2
returns 另一个 函数
\x -> foo1 (foo2 x)
如果应用于 另一个 参数 bar
将 return 由 foo1 (foo2 bar)
.
计算的值
在Python这样的语言中,它看起来像
compose1 = lambda f: lambda g: lambda x: f(g(x))
因为 Python 函数默认不柯里化,这是一个独特的
来自 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
你不必想太多。 (\f -> (\g -> (\x -> f (g x) ) ) )
只是参数 f
和 一些结果 ... 的函数,这恰好又是一个函数,但原则上它与函数没有什么不同结果是一个数字。这只是一些黑匣子...
\f -> ██
现在,当您实际将此 lambda 应用于某些 f
时,您可以访问黑盒。例如,我可以将它应用于 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
或者实际上只是 .
将整个 lambda 函数想象成一个黑盒子。从签名中我们知道有三个箭头“->”分隔每个参数。这告诉你这个黑盒子接收到 3 个实参:f g x。它将 f 应用于将 g 应用于 x 的结果。通过查看其命名函数等价物更容易理解。
compose f g x = f (g x)
compose' f g = \x -> f (g x)
我正在尝试建立理解一系列嵌入式匿名表达式的最佳方法,例如:
(\f -> (\g -> (\x -> f (g x) ) ) )
在Haskell。我对更简单的表达式没有太多麻烦,例如:
(\x -> x + 1)
其中指出该函数接受一个数字和 returns 一个数字:
Num a => a -> a
但是当事情像这样嵌入时,我就迷路了。我试图理解它是匿名函数立即将参数从 f
传递到 g
再到 x
,然后我应该开始编写类型,因为它是使用变量的地方.但我已经尝试合理化可能四五个不同的解释,并且我一直在关注最内层函数中看起来像递归函数调用的东西。
这个问题的类型可以用更简单的方式解决吗?
这只是柯里化的一个例子。 Haskell 为此提供语法糖:
\f g x -> f (g x)
在任何一种情况下,将函数应用于参数 foo1
return 函数
\g x -> foo1 (g x)
将其应用于一个函数 foo2
returns 另一个 函数
\x -> foo1 (foo2 x)
如果应用于 另一个 参数 bar
将 return 由 foo1 (foo2 bar)
.
在Python这样的语言中,它看起来像
compose1 = lambda f: lambda g: lambda x: f(g(x))
因为 Python 函数默认不柯里化,这是一个独特的
来自 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
你不必想太多。 (\f -> (\g -> (\x -> f (g x) ) ) )
只是参数 f
和 一些结果 ... 的函数,这恰好又是一个函数,但原则上它与函数没有什么不同结果是一个数字。这只是一些黑匣子...
\f -> ██
现在,当您实际将此 lambda 应用于某些 f
时,您可以访问黑盒。例如,我可以将它应用于 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
或者实际上只是 .
将整个 lambda 函数想象成一个黑盒子。从签名中我们知道有三个箭头“->”分隔每个参数。这告诉你这个黑盒子接收到 3 个实参:f g x。它将 f 应用于将 g 应用于 x 的结果。通过查看其命名函数等价物更容易理解。
compose f g x = f (g x)
compose' f g = \x -> f (g x)