F#函数的F#有趣行为

时间:2013-06-06 07:17:05

标签: f# f#-scripting

我有一个功能

// Will perform a given function twice
let twice f = (fun x -> f (f x))

然后我有类似的东西。

// Take x add 1
let f x = x+1

根据我两次调用的方式,它与左关联性的行为不同。

(twice (twice (twice (twice f)))) 0;; // Outputs 16
twice twice twice twice f 0;; // Outputs 65536

如果我再添加两次我的程序会执行StackOverflow,但到目前为止它似乎没有模式,这让我发疯。

设k是调用twice的次数。

非咖喱是2 ^ k得到答案。

Curried非常奇怪。 假设1:当调用次数小于4时,它看起来像2 ^(2 ^(k-1)),但当k为4时,它的行为类似于2 ^(2 ^ k)< / p>

有没有人看到这种模式?或者你可以运行它超过k = 4来证明它吗?

2 个答案:

答案 0 :(得分:3)

这是简单的优先规则,表现很奇怪(提示是65536 = 2 ^ 16)。在第二种情况下,您实际上是在创建指数的f调用而不是预期的线性增长。

当您在第二个案例中展开一个图层时,您将获得

twice twice twice (twice twice twice (f)) 0

,当您撰写更多twice

时,术语数量将呈指数级增长

答案 1 :(得分:1)

事实上,这完全取决于相关性。当你写作时,

let x1 = twice twice twice twice f 0

等于

let x11 = (((twice twice) twice) twice) f 0

这导致了呼叫顺序的指数增长:每个twice呼叫应该调用f x两次。相反,它递归调用自身,而只有最内在的调用会调用f

您可以查看该函数的原型:

let y1: ( _ -> _ -> int) = twice twice twice twice
// val y1: ((int -> int) -> int -> int)

使关联性能很好的最小代码是:

// note we need to specify a type here
let y2: ( _ -> _ -> int) = twice >> twice >> twice >> twice
// the same with all arguments
let x2 = (twice >> twice >> twice >> twice) f 0

let y3 = f |> twice |> twice |> twice |> twice
let x3 = (f |> twice |> twice |> twice |> twice) 0