gpt4 book ai didi

haskell - Haskell "understand"柯里化(Currying)函数定义吗?

转载 作者:行者123 更新时间:2023-12-02 14:02:53 25 4
gpt4 key购买 nike

在 Haskell 中,函数始终采用一个参数。多个参数通过 Currying 实现。既然如此,我可以看到下面如何将两个参数的函数定义为“func1”。它是一个返回函数(闭包)的函数,该函数将外部函数的单个参数添加到返回函数的单个参数中。

然而,尽管这就是柯里化(Currying)函数的工作方式,但这并不是定义二参数函数的常规 Haskell 语法。相反,我们被教导定义这样一个函数,如“func2”。

我想知道 Haskell 如何理解 func2 的行为应该与 func1 相同。 func2 的定义中没有任何内容表明它是一个返回函数的函数。相反,它实际上看起来像一个双参数函数,我们被告知的东西不存在!

这里有什么技巧吗? Haskell 是不是一出生就知道我们可以用教科书上的方式定义多参数函数,并且它们无论如何都会按照我们期望的方式工作?也就是说,这是一个似乎没有明确记录的语法约定(Haskell 知道你的意思,并将为你提供缺少的函数返回),还是还有其他一些魔法在起作用,或者我缺少什么?

func1 :: Int -> (Int -> Int)
func1 x = (\y -> x + y)

func2 :: Int -> Int -> Int
func2 x y = x + y

main = do
print (func1 7 9)
print (func2 7 9)

最佳答案

语言本身中,编写f x y z = _形式的函数定义相当于f =\x y z -> _,相当于f =\x ->\y ->\z -> _。这没有任何理论上的理由;只是那些嵌套的 lambda 抽象令人眼花缭乱,每个人都认为牺牲一点学究气来为其制作一些语法糖就好了。这就是表面上的全部内容,并且可能是您目前需要了解的全部内容。

但是,在该语言的实现中,事情变得更加棘手。在最常见的实现 GHC 中,f x y = _f =\x ->\y -> _ 之间实际上是有区别的。当 GHC 编译 Haskell 时,它会为声明分配元数f 的前一个定义的元数为 2,后者的元数为 0。从 GHC.Base

中获取 (.)
(.) f g = \x -> f (g x)

(.) 具有元数 2,即使其类型为 ((b -> c) -> (a -> b) -> a -> c) 表示最多可以应用三次。这会影响优化:GHC 只会内联一个饱和的函数,或者至少应用了与其参数数量一样多的参数。在调用 (maximum .) 时,(.) 不会内联,因为它只有一个参数(它是不饱和)。在调用 (maximum . f) 中,它将内联到 \x -> maximum (f x),并且在 (maximum .f) 1(.) 将首先内联到 lambda 抽象(生成 (\x -> Maximum (f x)) 1),其中将 beta-reduce 至最大值 (f 1)。如果(.)被实现

(.) f g x = f (g x)

(.) 的数量为 3,这意味着它内联的频率会降低(特别是 f . g 情况,这是一个对于高阶函数来说非常常见的论点),可能会降低性能,这正是它的评论所说的:

Make sure it has TWO args only on the left, so that it inlineswhen applied to two functions, even if there is no final argument

最终答案:根据语言的语义,这两种形式应该是等价的,但在 GHC 中,这两种形式在优化方面具有不同的特征,即使它们总是给出相同的结果。

关于haskell - Haskell "understand"柯里化(Currying)函数定义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47142209/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com