了解Haskell中的嵌入式匿名函数?

时间:2016-12-06 16:18:00

标签: haskell anonymous-function

我正在尝试建立理解一系列嵌入式匿名表达式的最佳方法,例如:

(\f -> (\g -> (\x -> f (g x) ) ) )

在Haskell。对于简单的表达式我没有太多麻烦,例如:

(\x -> x + 1) 

其中声明该函数采用Number并返回一个数字:     Num a => a -> a

但是当事情像这样被嵌入时我会迷失方向。我试图理解它是匿名函数立即将参数从f传递到gx,然后我应该开始编写输入,因为它是使用变量的地方。但我已经尝试合理化了四五种不同的解释,并且我一直在内心函数中看起来像一个递归函数调用。

可以更容易地找出这个问题的输入吗?

3 个答案:

答案 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),其中fgx是我们'已经申请:

(\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)