【问题标题】:Find Haskell functions f, g such that f g = f . g找到 Haskell 函数 f, g 使得 f g = f 。 G
【发布时间】:2024-01-19 21:29:01
【问题描述】:

在学习 Haskell 时,我遇到了一个挑战,要找到两个函数 fg,这样 f gf . g 是等价的(并且总计,所以像 f = undefinedf = (.) f don不算)。给定的解决方案是fg 都等于\x -> x . x(或join (.))。

(我注意到这不是 Haskell 特有的;它可以用纯组合逻辑表示为“找到fg 使得f g = B f g”,然后给定的解决方案将转换为@987654334 @.)

我理解为什么当我扩展给定解决方案时它会起作用,但我不明白如果你还不知道它是如何找到它的。这是我能走多远:

  • f g = f . g(给定)
  • f g z = (f . g) z(两边的eta-expansion)
  • f g z = f (g z)(简化 RHS)

我不知道如何从那里着手。在尝试找到解决方案时,我接下来会做什么?

【问题讨论】:

  • 也许一个开始的地方是弄清楚他们必须拥有什么类型。事实证明,要使表达式有意义,它们必须具有多态类型,这可以告诉你很多可能的实现。
  • fidg 为任意函数。 id g = g = id . g.

标签: haskell functional-programming lambda-calculus combinatory-logic


【解决方案1】:

我发现通过考虑 Church 数字计算可以找到一系列解决方案。在 Church 编码中,乘法是通过组合 Church 数字来执行的,而乘方是通过将基数应用于指数来执行的。因此,如果f 是某个数字x 的Church 编码,而g 是某个数字y 的Church 编码,那么f g = f . g 意味着y^x = x*y。该方程的任何非负整数解都转化为原始问题的解。例子:

  • x=1, y=0, f=id, g=const id
  • x=1, y=1, f=id, g=id
  • x=1, y=2, f=id, g=join (.)
  • 由于y^1 = y = 1*y 适用于所有y,因此f=id 适用于所有教会数字g 是有道理的。确实如此,事实上,正如 Rein Henrichs 所指出的,所有g 都是如此,而且这很容易通过检查来验证。
  • x=2, y=0, f=join (.), g=const id
  • x=2, y=2, f=join (.), g=join (.)
  • x=3, y=0, f=(.) <*> join (.), g=const id
  • 由于0^x = 0 = x*0 表示所有正数x,因此g=const id 适用于所有正数Church 数字f 是有道理的。 (它不适用于 f=const id,教会数字 0,这是有道理的,因为 0^0 是一个不确定的形式。)

【讨论】:

  • 0^0 在这里不是不确定的,它是 1(自己检查它是 id)。这是因为我们在这里处于离散情况而不是连续情况。
  • @Potato44 是的;我想我的意思是它通常是不确定的,并且恰好在 Church 编码中评估为 1。