72

大学2年生のとき、私たちはHaskellを「教えられ」ました。私はそれについてほとんど何も知らず、関数型プログラミングについてもほとんど知りません。

関数型プログラミングとは何ですか、なぜ関数型プログラミングの代わりにそれを使用したいのですか?Cは関数型プログラミング言語であると考えるのは正しいですか?

4

8 に答える 8

91

関数型言語の重要な機能の1つは、ファーストクラス関数の概念です。アイデアは、関数をパラメーターとして他の関数に渡し、それらを値として返すことができるということです。

関数型プログラミングには、状態を変更しないコードの記述が含まれます。そうする主な理由は、関数を連続して呼び出すと同じ結果が得られるようにするためです。第一級関数をサポートする任意の言語で関数型コードを書くことができますが、Haskellのように、状態を変更できない言語もあります。実際、(テキストの印刷などの)副作用をまったく発生させることは想定されていません。これは完全に役に立たないように思われます。

Haskellは代わりにIOへの異なるアプローチを採用しています:モナド。これらは、インタプリタのトップレベルによって実行される必要なIO操作を含むオブジェクトです。他のレベルでは、それらは単にシステム内のオブジェクトです。

関数型プログラミングにはどのような利点がありますか?関数型プログラミングでは、各コンポーネントが完全に分離されているため、バグの可能性が少ないコーディングが可能です。また、再帰関数と第一級関数を使用すると、通常はコードの構造を反映した単純な正しさの証明が可能になります。

于 2008-08-23T15:19:17.390 に答える
24

関数型プログラミングとは

今日一般的に使用されている「関数型プログラミング」には、2 つの異なる定義があります。

古い定義 (Lisp に由来する) では、関数型プログラミングはファーストクラスの関数を使用したプログラミングに関するものです。つまり、関数は他の値と同じように扱われるため、関数を引数として他の関数に渡すことができ、関数は戻り値の中で関数を返すことができます。mapこれは、 andなどの高階関数の使用で最高潮に達しreduceます (Google で頻繁に使用される単一の操作として聞いたことがあるかもしれませんがmapReduce、当然のことながら、これは近縁です!)。.NET の型System.FuncSystem.Actionは、C# で高階関数を使用できるようにします。C# ではカリー化は実用的ではありませんが、関数など、他の関数を引数として受け入れる関数は一般的Parallel.Forです。

新しい定義 (Haskell によって普及) では、関数型プログラミングは、突然変異を含む副作用を最小化および制御すること、つまり、式を構成することによって問題を解決するプログラムを作成することでもあるというものです。これは、より一般的には「純粋関数型プログラミング」と呼ばれます。これは、「純粋に機能的なデータ構造」と呼ばれるデータ構造への非常に異なるアプローチによって可能になります。問題の 1 つは、従来の命令型アルゴリズムを純粋に機能的なデータ構造を使用するように変換すると、通常、パフォーマンスが 10 倍低下することです。LinqHaskell は現存する唯一の純粋な関数型プログラミング言語ですが、 .NETのようなライブラリを使用して、その概念がメインストリーム プログラミングに忍び込みました。

非関数型プログラミングの代わりにどこで使用したいですか

どこにでも。C# のラムダは、現在、大きな利点を示しています。C++11 にはラムダがあります。現在、高階関数を使用しない言い訳はありません。F# のような言語を使用できる場合は、型推論、自動一般化、カリー化、部分適用 (およびその他の多くの言語機能!) も利用できます。

C は非関数型プログラミング言語であると考えるのは正しいですか?

はい。Cは手続き型言語です。void *ただし、関数ポインターをC で使用することにより、関数型プログラミングの利点の一部を得ることができます。

于 2013-01-27T16:15:40.883 に答える
6

最近投稿されたCoDeMagのF#"101"に関するこの記事をチェックする価値があるかもしれません。

また、Dustin Campbellは素晴らしいブログを持っており、F#に慣れるまでの彼の冒険に関する多くの記事を投稿しています。

これらがお役に立てば幸いです:)

編集:

また、関数型プログラミングについての私の理解は、インスタンス/ステートフルオブジェクトではなく、すべてが関数または関数のパラメーターであるということです。しかし、間違っている可能性があります。時間があります!:)

于 2008-08-23T15:08:20.897 に答える
4

John the Statisticianのサンプルコードは関数型プログラミングを示していません。関数型プログラミングを行っている場合、重要なのは、コードが割り当てなし(record = thingConstructor(t)割り当て)であり、副次的効果(localMap.put(record)副作用のあるステートメント)がないことです。 。これらの2つの制約の結果として、関数が実行するすべてのことは、引数と戻り値によって完全にキャプチャされます。C ++を使用して関数型言語をエミュレートする場合は、統計家のコードを見た目どおりに書き直します。

RT getOrCreate(const Tthing、
                  const Function <RT <T >> thingsConstructor、
                  const Map <T、RT <T >> localMap){
    localMap.contains(t)を返しますか?
        localMap.get(t):
        localMap.put(t、thingConstructor(t));
}

副作用なしのルールの結果として、すべてのステートメントは戻り値の一部であり(したがって、最初returnに来る)、すべてのステートメントは式です。関数型プログラミングを強制する言語では、キーワードが暗黙指定され、ifステートメントはC++の演算子のように動作します。return?:

また、すべてが不変であるため、通常のC ++またはJavaプログラムのように、元のlocalMapを変更するのではなく、 localMaplocalMap.putの新しいコピーを作成して返す必要があります。localMapの構造によっては、コピーによって元のポインターへのポインターが再利用され、コピーする必要のあるデータの量が減る可能性があります。

関数型プログラミングの利点のいくつかには、関数型プログラムが短く、関数型プログラムを変更するのが簡単であるという事実が含まれます(考慮すべき隠れたグローバル効果がないため)。最初の場所。

ただし、機能プログラムは(実行する必要のあるすべてのコピーのために)実行が遅くなる傾向があり、メモリアドレスを処理する他のプログラム、オペレーティングシステムプロセス、またはオペレーティングシステムとうまく相互作用しない傾向があります。バイトのブロック、およびその他のマシン固有の機能しないビット。非相互運用性の程度は、機能の純度の程度、および型システムの厳密さと逆相関する傾向があります。

より人気のある関数型言語は、本当に、本当に厳密な型システムを持っています。OCAMLでは、整数と浮動小数点の計算を組み合わせたり、同じ演算子を使用したりすることはできません(+は整数の加算、+。は浮動小数点の加算)。これは、特定の種類のバグをキャッチするタイプチェッカーの能力をどれだけ高く評価しているかに応じて、長所または短所のいずれかになります。

関数型言語はまた、非常に大きなランタイム環境を持つ傾向があります。Haskellは例外です(GHC実行可能ファイルはコンパイル時と実行時の両方でCプログラムとほぼ同じくらい小さいです)が、SML、Common Lisp、およびSchemeプログラムは常に大量のメモリを必要とします。

于 2009-02-18T00:27:26.463 に答える
3

はい、あなたはCが関数型ではない言語であると考えるのは正しいです。Cは手続き型言語です。

于 2008-08-23T15:10:44.727 に答える
3

私は関数型プログラミングを使用して、より抽象的なバージョンを作成し、代わりにそれを使用することで、繰り返しの作業を節約することを好みます。例を挙げましょう。Javaでは、構造を記録するためのマップを作成し、getOrCreate構造を作成することがよくあります。

SomeKindOfRecord<T> getOrCreate(T thing) { 
    if(localMap.contains(thing)) { return localMap.get(thing); }
    SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(thing);
    localMap = localMap.put(thing, record);
    return record; 
}

これは非常に頻繁に発生します。今、私は関数型言語で書くことができました

RT<T> getOrCreate(T thing, 
                  Function<RT<T>> thingConstructor, 
                  Map<T,RT<T>> localMap) {
    if(localMap.contains(thing)) { return localMap.get(thing); }
    RT<T> record = thingConstructor(thing);
    localMap = localMap.put(thing,record);
    return record; 
}

そして、私はこれらの新しいものを二度と書く必要はないでしょう、私はそれを継承することができました。しかし、私は継承するよりも良いことをすることができました、私はこのことのコンストラクターで言うことができました

getOrCreate = myLib.getOrCreate(*,
                                SomeKindOfRecord<T>.constructor(<T>), 
                                localMap);

(ここで、*は一種の「このパラメーターを開いたままにする」表記であり、一種のカリー化です)

次に、ローカルのgetOrCreateは、継承の依存関係なしで、すべてを1行で書き留めた場合とまったく同じになります。

于 2008-08-23T15:31:48.297 に答える
2

F#で良いテキストを探しているなら

Expert F#はDonSymeによって共同執筆されました。F#の作成者。彼は特に.NETでジェネリックスに取り組み、F#を作成できるようにしました。

F#はOCamlをモデルにしているため、OCamlテキストはF#の学習にも役立ちます。

于 2008-08-23T17:54:14.040 に答える
1

関数型プログラミングとは? 役に立つ

関数型プログラミングとは、純粋な関数を記述し、隠れた入力と出力を可能な限り削除して、できるだけ多くのコードで入力と出力の関係のみを記述することです。

明示的なwhenパラメータを優先

public Program getProgramAt(TVGuide guide, int channel, Date when) {
  Schedule schedule = guide.getSchedule(channel);

  Program program = schedule.programAt(when);

  return program;
}

以上

public Program getCurrentProgram(TVGuide guide, int channel) {
  Schedule schedule = guide.getSchedule(channel);

  Program current = schedule.programAt(new Date());

  return current;
}

関数型言語は、副作用に対して積極的に敵対的です。副作用は複雑さであり、複雑さはバグであり、バグは悪魔です。関数型言語は、副作用にも敵対するのに役立ちます。

于 2016-01-07T08:24:20.110 に答える