gpt4 book ai didi

haskell - 函数组合及其表示

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

我想知道:

1) 以下功能完全相同:

inc = (+1)
double = (*2)

func1 = double . inc
func2 x = double $ inc x
func3 x = double (inc x)
func4 = \x -> double (inc x)

2) 为什么不 func5编译?
func5 = double $ inc        -- doesn't work

最佳答案

Are these functions exactly the same?



其实,不!有一些非常细微的差异。首先,阅读 dreaded monomorphism restriction .简而言之,默认情况下,类多态函数被赋予不同的类型,无论它们是否“显然”是函数。在您的代码中,这种差异不会表现出来,因为 incdouble不是“显然”的函数,因此被赋予单态类型。但如果我们稍作改动:
inc, double :: Num a => a -> a
inc = (+1)
double = (*2)

func1 = double . inc
func2 x = double $ inc x
func3 x = double (inc x)
func4 = \x -> double (inc x)

那么在ghci中我们可以观察到 func1func4 -- 不是“明显”的函数 -- 被赋予了单态类型:
*Main> :t func1
func1 :: Integer -> Integer
*Main> :t func4
func4 :: Integer -> Integer

func2func3被赋予一个多态类型:
*Main> :t func2
func2 :: Num a => a -> a
*Main> :t func3
func3 :: Num a => a -> a

第二个细微的区别是这些实现可能有(非常轻微的)不同的评估行为。自 (.)($)是函数,你可能会发现调用 func1func2在它们可以运行之前需要进行一些评估。例如,可能是第一次调用 func1 3像这样进行:
func1 3
= {- definition of func1 -}
(double . inc) 3
= {- definition of (.) -}
(\f g x -> f (g x)) double inc 3
= {- beta reduction -}
(\g x -> double (g x)) inc 3
= {- beta reduction -}
(\x -> double (inc x)) 3

而第一次调用,例如 func4 3以更直接的方式到达这一点:
func3 3
= {- definition of func3 -}
(\x -> double (inc x)) 3

不过,我不会太担心这个。我希望在开启优化的 GHC 中,对 (.) 的饱和调用和 ($)内联,消除这种可能的差异;即使没有,这确实是一个非常小的成本,因为每个定义可能只发生一次(而不是每次调用一次)。

Why doesn't func5 compile?



因为你不想让它编译!想象一下。让我们看看我们将如何评估 func5 3 .我们会看到我们“卡住了”。
func5 3
= {- definition of func5 -}
(double $ inc) 3
= {- definition of ($) -}
(\f x -> f x) double inc 3
= {- beta reduction -}
(\x -> double x) inc 3
= {- beta reduction -}
double inc 3
= {- definition of double -}
(\x -> x*2) inc 3
= {- beta reduction -}
(inc * 2) 3
= {- definition of inc -}
((\x -> x+1) * 2) 3

现在我们正在尝试将一个函数乘以 2。目前,我们还没有说函数的乘法应该是什么(甚至,在这种情况下,“两个”应该是什么!),所以我们“卡住了”——没有什么可以进一步评估的了。这不好!我们不想在这么复杂的术语中“陷入困境”——我们只想在简单的术语上陷入困境,比如实际数字、函数等。

我们可以通过在开始时观察到 double 来防止这整个困惑。只知道对可以乘法的东西进行操作,还有 inc不是可以倍增的东西。所以这就是类型系统所做的:它进行这样的观察,并且在很明显会发生一些古怪的事情时拒绝编译。

关于haskell - 函数组合及其表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19621134/

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