2

我有以下函数签名,并希望实现一个实现它的 haskell 函数。

method :: (a -> (a -> b)) -> (a -> b)

尽管我尝试了各种方法来做到这一点,但我似乎错过了一个起点。我想我也许可以用 (>>=) 之类的壮举来做到这一点,但我不太确定。由于我对haskell 相当陌生,我什至不太确定如何输出函数而不是像Int 或Bool 这样的值。

4

1 回答 1

5

让我们使用 la Agda 的“洞驱动开发”来解决这个问题。我们想method在最高级别定义哪个是函数。我们使用 lambdas 创建函数,因此我们可以从那里开始并给自己留下一些漏洞。

method = \f     ->     #{1}

我们知道这一点f :: (a -> (a -> b))和我们的洞,#{1} :: (a -> b)。我们需要以某种方式使用f来创建#{1}. 既然我们现在想要另一个函数#{1}, 让我们使用另一个 lambda

method = \f     ->     \a      ->     #{2}

现在a :: a#{2} :: b。我们需要生成一个b使用fa类型的f :: (a -> (a -> b))a :: a。希望这越来越清楚,但让我们继续分解它。

类型表示法的约定是函数箭头(->)是右结合的,所以每当我们看到时,a -> (b -> c)我们都可以将其视为a -> b -> c. 此外,我们在两个参数函数 likea -> b -> c和 pairs函数之间存在等价性(a, b) -> c。这个等价是curry/ uncurry,但在我们的例子中很有用。

让我们重写f为等价函数f' :: (a, a) -> bf' (a, b) = f a b鉴于我们总是可以使用“对角线”函数diag :: a -> (a,a)来创建同质对,我们就完成了。我们可以使用从任何f'创建一个,我们可以使用从任何创建一个。我们想要一个,我们有一个。b(a,a)diag(a, a)aba

method = \f     ->     \a      ->     f' (diag a)
  where
    f' (a, b) = f a b
    diag a    = (a, a)

或者

method f a = f a a

因此,您可能会将某个更通用的功能缩小method为仅作用于. 使这一点更加清晰的类型签名使用了我们的技巧:diagonalsf'

method :: ((a, a) -> b) -> (a -> b)
method f' a = f' (a, a)
于 2013-06-21T16:27:38.780 回答