繁体   English   中英

Haskell 高阶函数和关联性

[英]Haskell Higher Order Functions and Associativity

我正在学习 FP,在玩过 GHCi 之后有些困惑。

假设我有 2 个简单的功能:

twice :: (a -> a) -> (a -> a)
twice f a = f (f a) -- Equation 1

double :: Int -> Int
double = \x -> x * 2

将评估分解twice twice twice double 3 (注意 3x twice +1x double ),我会:

{-
   twice twice twice double 3
== (twice twice twice double) 3
== (twice twice (twice double)) 3
== (twice (twice (double double 3))) 
== (twice ((double double) (double double 3))) 
== (((double double) (double double)) ((double double) (double double 3))) 
== 768
-}
  • 这个对吗?
  • 据此,如果我对twice的定义更改为twice fa = ffa -- Equation 2 ,我应该将评估分解为左结合性,如下:
{-
   twice (twice twice double) 3
== (twice twice double) (twice twice double) 3
== ((twice double)(twice double)) ((twice double)(twice double)) 3
== ((double double)(double double)) ((double double)(double double)) 3
== (double (double (double (double (double (double (double (double 3 ) ) ) ) ) ) )
== 768
-}

正确的?

  • 然而,最奇怪的部分是 GHC REPL 给了我196608 (2^16*3) 的答案:
> twice twice twice double 3
196608

这让我很困惑。 我会在哪里犯错? 谢谢。

正如评论所说,function 应用程序是左关联的,所以:

twice twice twice double 3 == (((twice twice) twice) double) 3

which is not the same as:     twice (twice twice double 3)

根据您的评论要求:请注意, twice返回相同类型的参数。 所以, twice twice的类型就是((a -> a) -> (a -> a))

现在,让我们扩展整个表达式:

(((twice twice) twice) double) 3 ==> ((twice (twice twice)) double) 3
                                 ==> (((twice twice) ((twice twice) double)) 3
                                 ==> (twice (twice ((twice twice) double))) 3
                                 ==> (twice (twice (twice (twice double)))) 3

twice double ==> double^2
twice (twice double) ==> double^4
twice (twice (twice double)) ==> double^8
twice (twice (twice (twice double))) == double^16

和你发现的double^16 3 == 2^16 * 3

假设n是一个自然数,并且gn定义如下,非正式地:

g n = \f x -> f (f (f (.... (f x))))  -- n times f on x

在您的情况下, twice fx = g 2 fx

那么,可以证明

g n (g m) f x = g (m^n) f x

的确,

g n (g m) f x =
(g m (g m (g m (g m .... (g m f))))) x =  -- n times (g m) on f

所以它采用“ m次重复f ” function,然后重复该m次以形成另一个 function,然后再重复该m次,...每一步都将f的应用次数乘以m ,所以我们得到m^n

回到你的案例

twice twice twice double 3 =
g 2 (g 2) (g 2) double 3 =
g (2^2) (g 2) double 3 =
g (2^(2^2)) double 3 =
double (double (double .... 3)) -- 2^(2^2) = 2^4 = 16 times

所以,我们得到316倍,得到3 * 2^16 = 196608

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM