什么是“无点”样式(在函数式编程中)?


100

我最近注意到的一句话是“无点”风格的概念。

首先,有一个问题,还有这个问题。

然后,我发现他们在这里提到“可能值得讨论的另一个主题是作者对点自由样式的厌恶”。

什么是“免积分”风格?有人可以给出一个简洁的解释吗?它与“自动”咖喱有关系吗?

为了了解我的水平-我一直在教自己Scheme,并且编写了一个简单的Scheme解释器...我了解“隐式”的currying是什么,但是我不知道任何Haskell或ML。


3
只需注意:要了解为什么将其称为免积分,请访问Pointfree /,但是pointfree有更多积分!在HaskellWiki。
PetrPudlák2012年

Answers:


66

只需查看Wikipedia文章即可获得您的定义:

隐式编程(无点编程)是一种编程范式,其中函数定义不包含有关其自变量的信息,而是使用组合器和函数组合而不是变量。

Haskell示例:

常规(您明确指定参数):

sum (x:xs) = x + (sum xs)
sum [] = 0

无点(sum没有任何显式参数-只是+以0开头的折叠):

 sum = foldr (+) 0

或更简单:g(x) = f(x)您可以编写,而不是g = f

是的:它与currying(或类似函数组合的操作)密切相关。


8
啊,我明白了!因此,您总是仅通过组合其他功能而不是声明参数来构建新功能...非常优雅!
Paul Hollingsworth,2009年

22
我真的不喜欢在编程时必须为变量/参数命名。这就是我喜欢无分的风格的一大原因!
马丁于2009年

2
它与Currying有什么关系?
万花筒

1
@kaleidic:因为没有变量名,所以需要组成部分应用的函数。这就是我们所谓的currying(或更准确地说,是通过currying使之成为可能)
Dario

1
你不是要sum (x:xs) ...代替sum sum (x:xs) ...吗?
Ehtesh Choudhury 2011年

33

无点样式意味着没有明确提到要定义的函数的参数,而是通过函数组合来定义函数。

如果您有两个功能,例如

square :: a -> a
square x = x*x

inc :: a -> a
inc x = x+1

如果要将这两个函数结合在一起进行计算x*x+1,则可以将其定义为“全点”,如下所示:

f :: a -> a
f x = inc (square x)

没有意义的替代方案是不谈论该论点x

f :: a -> a
f = inc . square

21
愚蠢的是,在Haskell中,“无点”方式通常看起来更尖(更长时间)。这种烦恼使人记忆深刻。(《 Real World Haskell》对此发表了评论。)

3
关于@Dan的评论,Pointfree HaskellWiki页面提供了为什么将其称为pointfree的解释。
文森特·萨瓦德

2
@丹:我不认为这是愚蠢的,因为Haskell点的意思是“那个圆算子”(虽然看起来更像°)。但是令人困惑,特别是当您不熟悉函数式编程语言时;关于haskell的每本介绍性书籍都应解释无点式。
塞巴斯蒂安·马赫

12

一个JavaScript示例:

//not pointfree cause we receive args
var initials = function(name) {
  return name.split(' ').map(compose(toUpperCase, head)).join('. ');
};

const compose = (...fns) => (...args) => fns.reduceRight((res, fn) => [fn.call(null, ...res)], args)[0];
const join = m => m.join();

//pointfree
var initials = compose(join('. '), map(compose(toUpperCase, head)), split(' '));

initials("hunter stockton thompson");
// 'H. S. T'

参考


5

无点样式意味着即使存在并且正在使用代码,代码也不会明确提及其参数。

由于函数的工作方式,这在Haskell中有效。

例如:

myTake = take

返回一个带有一个参数的函数,因此除非您也想这么做,否则没有理由显式键入该参数。


1
有时,它在Haskell 98中不起作用,如中所述myShow = showHaskell Wiki
Ehtesh Choudhury 2011年

-1

这是TypeScript中没有任何其他库的一个示例:

interface Transaction {
  amount: number;
}

class Test {
  public getPositiveNumbers(transactions: Transaction[]) {
    return transactions.filter(this.isPositive);

    //return transactions.filter((transaction: {amount: number} => transaction.amount > 0));
  }

  public getBigNumbers(transactions: Transaction[]) {
    // point-free
    return transactions.filter(this.moreThan(10));

    // not point-free
    // return transactions.filter((transaction: any) => transaction.amount > 10);
  }

  private isPositive(transaction: Transaction) {
    return transactions.amount > 0;
  }

  private moreThan(amount: number) {
    return (transaction: Transaction) => {
      return transactions.amount > amount;
    }
  }
}

您可以看到无点样式更“流利”并且更易于阅读。


那不是没有意义的风格,只是lambda和命名函数之间的区别。
kralyk

@kralyk我认为您错过了要点,this.moreThan(10)它不是命名函数,它是咖喱函数以及将隐式(因此没有点数)以a transaction作为输入的函数。
AZ。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.