Haskell中的函数约简如何工作?

时间:2018-09-29 19:50:57

标签: haskell functional-programming

为什么可以减少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

我只需要一些指导,可以找到答案并了解更多信息的任何资源将非常有帮助。

2 个答案:

答案 0 :(得分:8)

在Haskell中,没有 no 函数使用多个参数。所有函数都精确地使用 一个参数。

因此,如果您有一个类似add :: Int -> Int -> Int的函数,那么它实际上是add :: Int -> (Int -> Int)的缩写。

为什么括号很重要?因为它们显示了此概念的工作原理。如果我们具有此功能add,则可以使用例如14来创建函数应用程序,然后构造一个 new 函数,例如:

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。 f x 恰好是 f (反之亦然)被称为η-conversion [wiki]。在Haskell中,可以归结为重写:

f x = g x

收件人:

f = g

操作员没有什么不同。实际上,如果您在Haskell中编写a + b,则您编写了(+) a b,其中(+)是一个函数,或更冗长的((+) a) b

where子句中的f

f a b c = a + b

例如可以转换为:

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

答案 1 :(得分:3)

它称为eta reduction

您可能还会考虑部分应用。

> calculate :: Integer -> Integer -> Integer
> f :: Integer -> Integer -> Integer -> Integer
> (f 1) :: Integer -> Integer -> Integer

相似的问题-What does eta reduce mean in the context of HLint