「関数型プログラミング」の「ポイントフリー」スタイルとは何ですか?


100

私が最近気付いたフレーズは、「ポイントフリー」スタイルのコンセプトです...

最初に、この質問と、これもありました

その後、私はここで彼らが「議論する価値のあるもう1つのトピックは、ポイントフリースタイルに対する作者の嫌いなこと」に言及していることを発見しました

「ポイントフリー」スタイルとは?誰かが簡潔に説明できますか?「自動」カレーと関係がありますか?

私のレベルのアイデアを得るために-私は自分でSchemeを教えており、簡単なSchemeインタープリターを書きました...私は「暗黙の」カレーが何であるかを理解していますが、HaskellやMLを知りません。


3
ちょうどノート:それは呼ばれている理由を確認するpointfree訪問Pointfree /しかしpointfreeは、より多くのポイントを持っています!HaskellWikiで。
PetrPudlák12年

回答:


66

ウィキペディアの記事を見て、定義を取得してください。

暗黙的プログラミング(ポイントフリープログラミング)は、変数の代わりにコンビネータと関数構成[...]を使用して、関数定義に引数に関する情報が含まれないプログラミングパラダイムです。

Haskellの例:

従来型(引数を明示的に指定します):

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

ポイントフリー(sum明示的な引数はありません-これ+は0から始まるフォールドです):

 sum = foldr (+) 0

またはさらに単純化:の代わりにg(x) = f(x)、単にを書くこともできますg = f

だからはい:それはカレー(または関数構成のような操作)と密接に関連しています。


8
ええ、わかりました!そのため、引数を宣言するのではなく、常に他の関数を組み合わせるだけで新しい関数を作成します...非常にエレガントです!
ポールホリングスワース

22
私がプログラミングしているときに、変数や引数に新しい名前を付ける必要が本当に嫌いです。それがポイントフリースタイルが大好きな大きな理由の1つです。
Martijn、

2
それはカリーとどのように関係していますか?
カレイド

1
@kaleidic:変数名がないため、部分的に適用された関数を作成する必要があります。それが私たちがカレーと呼んでいるものです(より正確には、カレーによって可能になったものです)
Dario

1
あなたが意味するものではありません。sum (x:xs) ...代わりにsum sum (x:xs) ...
Ehtesh Choudhury、2011

33

ポイントフリースタイルとは、定義されている関数の引数が明示的に記述されておらず、関数が関数構成によって定義されていることを意味します。

次のような2つの関数がある場合

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

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

これらの2つの関数をを計算する関数に組み合わせる場合はx*x+1、次のように「ポイントフル」に定義できます。

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

ポイントフリーの代替案は、議論について話さないことxです:

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

21
愚かに、Haskellでは、「ポイントフリー」の方法は、通常、よりポイント(より多くの期間)に見える方法です。この煩わしさは、優れたニーモニックになります。(これについては、Real World Haskellの本がコメントしています。)
Dan

3
@Danのコメントに関して、Pointfree HaskellWikiページは、なぜそれがpointfreeと呼ばれるのかを説明しています。
Vincent Savard、2012年

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つ取る関数を返すため、必要な場合を除いて、引数を明示的に型指定する必要はありません。


1
Haskell 98では、のように機能しない場合がありmyShow = showます。Haskell wiki
Ehtesh Choudhury

-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;
    }
  }
}

ポイントフリースタイルの方が「流暢」で読みやすいことがわかります。


これはポイントフリースタイルではなく、ラムダと名前付き関数の違いです。
kralyk

@kralyk私はあなたがポイントを逃したと思いますthis.moreThan(10)、それは名前付き関数ではありません。それはカリー化された関数であり、暗黙的に(したがってポイントフリー)transaction入力をとる関数です。
AZ。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.