函数式编程中的参数化和减少

时间:2017-08-22 01:42:08

标签: functional-programming

我正在阅读一篇名为Why functional programming matters的论文。首先介绍说明列表中数字总和的计算。然后,公式强调可以通过将列表中的数字与列表其余部分的和函数相加来以递归方式计算此总和。将此过程称为reduce,然后写入reduce的定义可以通过参数化sum的定义来获得如下:

(reduce f x)  nil = x
(reduce f x) (cons a l)  =  f a ((reduce f x ) l)

我想知道的是,我们是否真的在函数式编程的程序中这样写,或者这仅仅是一个概念的例证?

同样是我的问题,它说明了另一个函数doubleaddcons,可以写成如下:

doubleall = reduce doubleandcons nil 

其中doubleandcons num list = cons (2*num) list

它实际上是在程序中编写的,还是只是一个概念的插图?

2 个答案:

答案 0 :(得分:0)

我无法作为一个整体与函数式编程世界对话,但我可以提供一个示例,说明如何使用像JavaScript这样支持函数式编程的通用语言来编写这样的东西。



const nums = [1, 2, 3, 4, 5];
const sum = nums.reduce((x, xs) => x + xs);
console.log(sum);




不确定这是否完全回答了你的问题。我假设您正在寻找减少功能概念的实际用例。

答案 1 :(得分:0)

本书使用了名为Miranda的Haskell的前身,因此示例是使用该语言编写的功能代码。我不太了解Miranda,但在Haskell中,您可以用一些不同的方式编写相同的内容,这对于典型的Algol程序员来说可能更容易阅读。

在Algol中,第一种风格的写作方式被称为多种方法,它最近很流行。例如在Perl6中:

multi factorial(0)      { 1 }
multi factorial(Int $x) { $x * factorial($x - 1) }

突然出现的中间地带是match,它是交换案例和解构的组合:

(define (factorial n)
  (match n
    [0 1]
    [n (* n (factorial (- n 1)))]))

在这里你可以看到它与在JS中编写它的更经典的方式非常相似:

function factorial (n) {
  return n === 0 ? 
         1 : 
         n * factorial(n - 1);
}

以上所有内容只是语法上的差异。它们的意思相同,并且编译器支持所有这些可能编译为相同目标代码的方式。

对于doubleall示例,它显示了Miranda的功能,如currying。如果您应用的参数太少,则结果是一个获取剩余参数的函数。

 
reduce doubleandcons nil [1, 2, 3] 
==> [2, 4, 6]

reduce doubleandcons nil
==> function of arity 1

(reduce doubleandcons nil) [1, 2, 3]
==> [2, 4, 6] 

虽然doubleandcons非常直接:

doubleandcons num list = cons (2*num) list

作为JS箭头功能,它将是

const doubleandcons = (num, list) => cons(2 * num, list)

在Miranda(和Haskell)中,您使用括号来更改默认关联。例如。如果没有它们(2*num) cons,它们就会被作为单独的参数提供。