首页 > 解决方案 > Haskell 中的函数缩减是如何工作的?

问题描述

为什么可以减少 Haskell 中的函数:

calculate :: Integer -> Integer -> Integer
calculate a b = f 1 a b
  where
     f :: Integer -> Integer -> Integer -> Integer
     f a b c = a + b

变成某事:

calculate :: Integer -> Integer -> Integer
calculate = f 1
  where
     f :: Integer -> Integer -> Integer -> Integer
     f a b c = a + b

我只需要一些指导,任何可以找到答案并阅读更多相关信息的资源都会非常有帮助。

标签: haskellfunctional-programming

解决方案


在 Haskell 中,没有任何函数可以接受多个参数。所有函数都只接受一个参数。

所以如果你有一个类似的函数add :: Int -> Int -> Int,那么这实际上是add :: Int -> (Int -> Int).

为什么括号很重要?因为他们展示了这个概念是如何运作的。如果我们有这个函数add,那么我们可以用 example 做一个函数应用程序14,然后我们构造一个函数,比如:

add14 :: Int -> Int
add14 = add 14

所以这意味着我们现在有一个函数,它再次接受一个参数(这里是一个Int),现在它会产生另一个Int,它通过向它添加 14 来实现,所以add14 25会产生39.

如果您编写add 14 25,则这不是具有两个参数的函数应用程序,您实际编写的是:

-- add 14 25 is equivalent to
(add 14) 25

因此,您首先使用 进行调用14,然后使用由此产生的函数并25作为参数进行调用。

为什么这很重要?因为这意味着如果你这样写

calculate = f 1

这意味着你的f 1, 构造一个函数,一个带有签名的函数Int -> (Int -> Int)。在 的头部创建参数calculate,并将这些添加到 的末尾f 1,因此没有意义:您已经构建了一个无论如何都接受这些参数的函数。所以它只会引入噪音。

lambda 演算中,重写λ x 的重写规则。fxf是(反之亦然)称为η-conversion [wiki]。在 Haskell 中,它归结为重写:

f x = g x

至:

f = g

运营商也不例外。事实上,如果你用a + bHaskell 编写,你写的是(+) a b, 带有(+)一个函数,或者更详细((+) a) b的 .

fwhere 子句中的:

f a b c = a + b

例如可以转换为:

f = (.) ((.) const) (+)

推荐阅读