使用reduce函数的标准ML semifactorial

时间:2013-11-21 03:11:01

标签: functional-programming sml smlnj

我正在遵循标准ML的本教程:http://homepages.inf.ed.ac.uk/stg/NOTES/node2.html,我遇到了这个问题:

  

如果n是奇数,则正整数n的半保密是1×3×5×...×n,如果n是偶数,则是2×4×6×...×n。使用reduce函数定义一个semifac函数,用于计算semifactorials。

Reduce定义为:

fun reduce (g, e, m, n, f) =
    if m > n then e else g (reduce (g, e, m, n-1, f), f n);

我花了几个小时搞乱这个问题,找不到令人满意的答案,不需要改变reduce功能。如果您将reduce重新定义为:

,问题就变得容易了
fun reduce' (g, e, m, n, f) = 
    if m > n then e else g (reduce'(g, e, m, n-2, f), f n);

最终解决方案为:

 fun semifactorial n = reduce'(fn (x,y) => x * y, 1, 1, n, fn x=>x);

我认为这是作者想要的,但我不确定。无论如何要解决这个问题而不改变reduce的定义?我认为有一些非常明显的功能方法可以做到这一点,但我看不出如何将减少量减少2而不是1(我的直觉说答案在于为g和f选择正确的函数值)。

2 个答案:

答案 0 :(得分:1)

您可以使用f来决定是否将索引相乘。如果奇偶校验相同,它应该只乘以它们。

fun sfact n = reduce(op*, 1, 1, n, fn k => if n mod 2 + k mod 2 = 1 then 1 else k);

答案 1 :(得分:1)

你非常接近。答案是选择正确的f。特别是f依赖于n的关键。

fun semifactorial n = reduce(fn (x,y) => x * y, 1, 1,
                             n, fn x => if x mod 2 = n mod 2 then x else 1)

应该有用。

或者,更干净一点:

fun foo n x = if (x + n) mod 2 = 0 then x else 1
fun semifactorial n = reduce((op* ), 1, 1, n, foo n x)

如果您的ML实现不支持任意精度整数,则此表单可能会因nx的特别大的值而失败。