Haskell 高阶函数和结合性

标签 haskell functional-programming ghc higher-order-functions

我正在学习 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 twice double 3(注意 3xtwice+1xdouble),我会:

{-
   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
-}
  • 这是正确的吗?
  • 根据 this ,如果我对 twice 的定义更改为 twice f a = f f a -- 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

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

最佳答案

正如评论所说,函数应用是左关联的,所以:

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 如您所见。

关于Haskell 高阶函数和结合性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62112599/

相关文章:

haskell - 如何在 nix-shell 中使用已安装的 ghc 和堆栈?

haskell - 省略显式 forall 会产生模棱两可的类型错误

Haskell 重构建议

parsing - 解析时,我需要添加什么才能将 monadUserState 与 alex 一起使用?

python - 将高阶函数从 Python 转换为 Haskell

haskell - 获取构造函数的名称

Ruby:Ruby 中优雅的数组初始化和返回

scala - 如何检查函数中元素的协变和逆变位置?

haskell - 是否可以加载编译后的代码来提示?

haskell - 如果跌倒