最も純粋な関数型プログラミング言語ですか?[閉まっている]


20

関数型プログラミングの学習に興味があります。そのためには、可能な限り純粋な関数型プログラミング言語を使用するように強制する必要があることは明らかです。それゆえ、私は多かれ少なかれ、関数型プログラミング言語の純度に応じた順序付けを求めています。

LispやClojure(またはScheme、Scalaなど)を学ぶ方が実際的だと思われますが、最近聞いたところでは、Haskellは関数型プログラミングの原理を誰かに教えるのに非常に難しいでしょう。私はまだこれについて確信がありませんので、私はあなたに尋ねています:最も純粋な関数型プログラミング言語はどれですか?最も純粋な関数型プログラミング言語の壮大なタイトルを求めて競合する人がいたら、注文は素晴らしいことです。


2
私は大学でミランダを学んだので偏見がありますが、不純物の気を散らすことなく関数型言語に没頭したい人にはHaskelをお勧めします。* 8 ')
マークブース

2
関数型プログラミングの学習が完了したら、表現型システムを使用して静的に型指定されたプログラミングも学習する必要があります。結合されたカテゴリー(関数型と型付きの両方)で、Coq> Haskell> OCaml> Scala>その他をお勧めします。CoqとHaskellの間に収まるあまり人気のない代替手段がいくつかあります(EpigramやAgdaなど)。HaskellはOCamlの表現力豊かなモジュールシステムを見逃しています。
ルクスタフィ

回答:


28

関数型言語の純度の程度を評価する尺度はありません。言語が副作用を許容する場合、それは不純であり、そうでない場合は純粋です。この定義では、Haskell、Mercury、Cleanなどは純粋な機能言語です。一方、Scala、Clojure、F#、OCamlなどは不純なものです。

編集:多分私はこれを「言語が型システムに知らせずに副作用許さないなら、それは純粋である。そうでなければ不純だ」と表現すべきだった。


6
完全ではありません:Haskellは副作用(IOモナド)を許可します。副作用の原因となるコードが明らかにそのようにマークされているだけです。私は純粋な/不純な言語について話すことはまったく役に立たないと思います(Haskellは命令的にプログラムできます!Gasp!) /不純。
フランクシェラー

8
@Frank:はい、Haskellは副作用を許可しますが、副作用を引き起こすコードをマークするだけではありません。また、副作用の原因となるコードを使用する場合でも参照の透明性を維持し、それが純粋なものになります-少なくとも多くの人々の純粋性の定義によって。もちろん、これは「副作用なし」のmissingfaktorの定義とは一致しません。
sepp2k

4
@Frank Sheararですが、IOモナド純粋なので、このような方法で話すのが便利です。main関数は基本的に巨大なステートトランスフォーマーであるため、コードではなく、ランタイムライブラリです。(main :: World -> World舞台裏のようなもの)
代替

1
私の言語にも参照の透明性があります。を書くだけでprogram = "some C code"、ランタイム環境がCコードを処理します。:-)
ダニエルルバロフ

3
画面への印刷は副作用なので、純粋に機能的なプログラムは退屈です。

15

学習はあなたの目標であり、プログラム自体を書くことではないので、Lambda Calculusよりも純粋になることはできません。

ラムダ計算は、コンピューターが発明される前から存在していました。いくつかの熟練した論理学者がそれに取り組んでいて、減算の方法を見つけました(しばらくの間、加算と乗算のみが可能であると理論化されていました)。

ブール値と数値、およびif一見何も考えられないことからどのように発明できるかを学ぶことは、あなたのタンクにそれ以上のガスを入れないでしょうが、それはあなたのタンクをもっと大きくします。


確かに、それよりも純粋ではないかもしれませんが、数学の壁を少し越えすぎています。私は今でもプログラミングを練習し、機能的な原則を吸収しながら新しい言語を学びたいです。しかし、機能的パラダイムの基礎をよりよく理解するため(そしてより大きなタンクを持つため)ラムダ計算を研究することは興味深いかもしれないことに同意します。
ジョアニス

2
証明を書くことはプログラムを書くことであり、プログラムを書くことは証明を書くことです。Curry–Howard同型について学習すると、1万行前にその数学の壁を越えたことに気付くでしょう。
マクニール

1
の単純な表現はありません-1
ダニエルルバロフ

2
@Mason Wheeler:λ-calculusだけでは、数値、または実際にはラムダ抽象化以外のデータはありません。特に指定のない限り、λ計算で数字について話す人は、おそらく自然数の教会のエンコードを意味します。ここで、数字nはn倍の関数合成で表されます。とはいえ、実際に誰かが試した後に減算を計算するのはそれほど大変なことだったのではないかと疑っています。加算の定義と減算が可能であるという知識だけを考えて、午後に自分で解決しました。
CAマッキャン

1
教会の数字を使用した減算は、ケースごとに分解したら簡単です。負の数をサポートするために、全体の(派生した)計算を構築します。
ドナルドフェローズ

6

不純な言語は、特に多くの機能的なトリックがコピーされた今、原則として、より馴染みのある命令型言語と実際には違いはありません。異なるのはスタイル-問題の解決方法です。

Haskellを純粋なものとして数えるか、IOモナドを不純なものとして数えるかに関わらず、Haskellスタイルはこのスタイルの極端な形であり、学ぶ価値があります。

Haskell IOモナドは、(もちろん)モナドの数学的理論から派生しています。しかし、命令型プログラマにとっては、モナドに逆戻りする方法がより理にかなっていると思います。

フェーズ1-純粋な関数型言語は、結果として大きな文字列値を簡単に返すことができます。この大きな文字列は、いくつかの要件指定パラメータから純粋に機能的な方法で導出された命令型プログラムのソースコードになります。次に、コードジェネレーターを実行する「上位」コンパイラーを構築し、生成されたコードを命令型言語コンパイラーに自動的にフィードします。

フェーズ2-テキストソースコードを生成するのではなく、厳密に型指定された抽象構文ツリーを生成します。命令型コンパイラは「上位」コンパイラに吸収され、ASTをソースコードとして直接受け入れます。これは、Haskellの機能に非常に近いものです。

しかし、これはまだ厄介です。たとえば、コード生成フェーズで評価される関数と、生成されたプログラムの実行時に実行される関数の2種類の関数があります。C ++の関数とテンプレートの区別に少し似ています。

したがって、フェーズ3では、2つを同じにします。同じ構文の同じ関数は、「コード生成」中に部分的に評価されるか、完全に評価されるか、まったく評価されません。さらに、再帰を支持して、すべてのループ構造ASTノードを破棄します。実際、特別な種類のデータとしてのASTノードの考えは完全に捨ててください。「リテラル値」のASTノードを持たず、値だけを持っているなどです。

これはほとんどIOモナドが行うことです-バインド演算子はプログラムを形成するための「アクション」を構成する方法です。特別なものではありません-ただの機能です。多くの式と関数は「コード生成」中に評価できますが、I / O副作用に依存するものは、特別なルールではなく、式。

一般にモナドは単なる一般化です-それらは同じインターフェースを持ちますが、抽象操作を異なる方法で実装するため、命令型コードの記述を評価する代わりに、他の何かを評価します。同じインターフェースを持っているということは、どのモナドを気にせずにモナドに対してできることがいくつかあるということです。

この説明は間違いなく純粋主義者の頭を爆発させますが、私にとっては、Haskellが興味深い理由のいくつかを説明しています。プログラミングとメタプログラミングの境界を曖昧にし、関数型プログラミングのツールを使用して、特別な構文を必要とせずに命令型プログラミングを改革します。

私がC ++テンプレートについて批判しているのは、それらが命令型言語の一種の壊れた純粋な機能的サブ言語であるということです-実行時ではなくコンパイル時に同じ基本機能を評価するには、完全に異なるスタイルを使用して再実装する必要がありますコーディングの。Haskellでは、不純物はそのタイプでそのようにラベル付けする必要がありますが、同じプログラムでメタプログラミングの意味とランタイムの非メタプログラミングの意味の両方でまったく同じ関数を評価できます-強い線はありませんプログラミングとメタプログラミングの間。

そうは言っても、基本的には型(および他のいくつかの要素)が第一級の値ではないため、標準のHaskellができないメタプログラミングの要素がいくつかあります。ただし、これに対処しようとする言語のバリエーションがあります。

Haskellについて私が言ったことの多くは、不純な関数型言語、そして時には命令型言語にも適用できます。Haskellは、このアプローチを取る以外に選択肢がないため、基本的にこの作業スタイルを学ぶことを強制されます。「CをMLで書く」ことはできますが、「CをHaskellで書く」ことはできません-少なくとも内部で何が起こっているかを学ぶことなしではできません。


ありがとうございました!C ++テンプレートの汎用性を関数自体に統合できたのではないかと思っていました。Haskellはこれを行うように見えますが、重要な部分は、コンパイル時にテンプレートから汎用関数を作成する同じエンジンが実行時にも評価できるように、これをコンパイル言語で実装できるかどうかです...
Milind R

5

私は個人的に言語を機能的純度の3つの層に分類しています。

  • 純粋関数型言語 -すなわち、単にランタイムとの相互作用を介して、純粋な機能とハンドル可変性とプログラム全体を扱うもの- Haskellは、おそらく標準的な例であります

  • 不純な機能言語 -すなわち、機能的なスタイルを強調するが、副作用を許容する言語Clojureは明らかにこのカテゴリに属し(STMフレームワークの一部として制御された方法で突然変異を許可します)、OCamlまたはF#

  • マルチパラダイム言語 -これらは何よりもまず関数型言語ではなく、など第一級関数を使用して機能的なスタイルをサポートすることができますScalaはここに良い例ですが、私はまた置くところはCommon Lispをこのカテゴリーにあなたも含めることができますJavaScriptのような言語。

あなたの状況では、まずHaskellを学び、次にClojureを学ぶことをお勧めします。これは私がやったことであり、私にとっては非常にうまくいきました!Haskellは美しく、最も純粋な機能原理を教えてくれます。Clojureははるかに実用的であり、心の中で非常に機能的でありながら、多くのことを成し遂げることができます。

3番目のカテゴリを関数型言語として実際にカウントしません(ただし、HaskellとClojureを学んだ後、それらを使用するときに関数型テクニックを利用することがよくあります!)


非常に厳しい制限内で、Cにも機能的な機能があります。(主な制限は、Cでは本当に恐ろしい関数の実行時合成にあります。ほとんどの人はそれができないと主張するほどです。)
ドナルフェローズ

2
@Donal Fellows:愚かさが無限に広がる限り、チューリング完全言語はすべて機能します。言語にLispインタープリターを実装し、それを使用するだけです。:]
CAマッキャン

すべてがチューリング完全であり、したがって他のすべてをエミュレートできるという観点をとる場合、パラダイムは無意味です。パラダイムについて考えるとき、言語が慣用的にするものとそれが落胆/予防するものに焦点を合わせなければなりません。私の見解では、関数型言語として数えるために、突然変異と副作用は単発的(不純なFP)または禁止(純粋なFP)でなければなりません。つまり、Cは機能しません。どちらもScalaのようなマルチパラダイム言語ではありません。
ミケラ

@mikera:あなたの答えは非常に興味深いと思います:Scalaが機能的ではなく、マルチパラダイムのみである場合、C ++ 11、C#、またはJava(ラムダの計画的導入)で機能的プログラミング機能をどのように判断しますか?
ジョルジオ

@Giorgio:あなたが言及するすべての言語の関数型機能はおそらく良いアイデアだと思う。それらは単に「関数型言語」にしない。または、逆方向から見ると、命令型のモナドIOを実行できるという事実は、Haskellを命令型言語にしません:-)。基本的にマルチパラダイム言語は、多くの異なるパラダイムの機能をまとめ、特定のスタイルを何よりも優先しない場合の結果です。IMHO C ++、C#、およびJavaはすべてマルチパラダイムに向かっていますが、クラスベースのOOPが依然として支配的であるため、まだそこにはありません。
ミケラ

3

純粋な関数型言語(純粋な関数(副作用のないルーチン)のみ)がある場合、入力の読み取りまたは出力の書き込みができないため、少し無意味です;)

これは本当に学習のためですので、私は、分離は必ずしもないと思う移動するための方法。関数型プログラミングはパラダイムです。どのパラダイムがどの問題に適しているか、さらに重要なことは、それらをどのように組み合わせることができるかを理解することが重要です。

私は今それを言います:プログラミングのやり方は愚かで非生産的です。重要なのは、プログラムが短く、書きやすく、保守しやすく、正しく動作することだけです。これをどのように達成するかは、プログラミングの流行とは関係ありません。- リチャード・ジョーンズ

それ以外に、「純度」を探しているなら、Pureを見てみたいかもしれません。ただし、Cルーチンの呼び出しは非常に簡単であるため、機能的に不純です(ただし非常に強力です)。


3

完全に真面目な答えではありませんが、Unlambdaは競争相手でなければなりません。SKIコンビネーター以上の「純粋な機能」を取得することはできません。


4
狂気!異端!副作用を持つコンビネーターのような不条理なのは、どのような純粋な言語ですか?いやいや ここで本当に欲しいのはLazy Kです。
CAマッキャン

2

Erlang、Haskell、Scheme、Scala、Clojure、F#

この質問は、おそらくあなたの検索で役立つでしょう。


本当に興味深い質問です。私はPLT-Scheme / Racketを使い始めましたが、まだSICPに目を向けていません... Real World Haskellは私にとっても非常に興味深いものです。
ジョアニス

Schemeは機能的なスタイルを奨励し、それが持っているset!...(とりわけ)
ダニエルLubarov

OCamlをお勧めします。これは私のお気に入りだからです。また、HaskellとF#が見落としているモジュールシステムがあります。
ルクスタフィ

@lukstafiは過去3年でhaskellが変更された可能性があります(クレイジーに成長していることは知っています)が、haskellには間違いなくモジュールがあります。
サラ

@kaiモジュールシステムとは、他のモジュールによってパラメーター化されたモジュールを意味します(モジュールの「ラムダ計算」)。
-lukstafi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.