为什么可以减少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
我只需要一些指导,可以找到答案并了解更多信息的任何资源将非常有帮助。
答案 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)
您可能还会考虑部分应用。
> calculate :: Integer -> Integer -> Integer
> f :: Integer -> Integer -> Integer -> Integer
> (f 1) :: Integer -> Integer -> Integer