*どんな*プログラムタスクも状態なしで表現できますか?


13

これは理論的な質問ですが、私が現在理解しているプログラミングの長年の後に、主にC ++を使用する「通常の」命令型テクニックです。

これにより、完全に状態指向のプログラムを、純粋に機能的で状態のない別の実装に技術的に置き換えることができるのではないかと思いました。

それは興味をそそるアイデアであり、関数型プログラミングには明確で優雅なものがあることを認めなければなりません。


1
関連するStackOverflowの答え:stackoverflow.com/questions/3722084/…–
jfriend00

ある時点から次の時点まで持続する状態があるかどうかは、使用するプログラミングパラダイムではなく、コーディングしている問題やタスクに依存します。ボタンがクリックされた回数をカウントしている場合、そのカウンターを記録する状態があることは明らかであり、使用するコーディング手法は関係ありません。プロセス中にカウントを追跡する状態が必要になります。そのため、その特定のタスクは、コーディングの方法に関係なく、途中の状態なしでは完了できません。
jfriend00

6
状態について議論したい場合; プログラム自体の場合のみ、明確に状態が必要です。ただし、可変状態と不変状態の両方を考えているように思えます。質問の意味を示すこともできます。
ビリーONeal

1
これは、すべてのプログラムを真のチューリングマシンに変換できるかどうかを尋ねるようなものです。技術的には、データベースを保存およびロードするプログラムであっても、チューリングマシンでこの動作をシミュレートすることは非常に困難になります。同様に、MVCアーキテクチャーのコントローラー側が削除されたプログラムを作成し、すべての呼び出しを行うこともできますが、処理がさらに難しくなります(プログラムをステートレスにするためには、基本的にコントローラーになります)。
ニール

回答:


17

簡単な答え:はい。ウィキペディアによると、計算の普遍的なモデルとしてのラムダ計算とチューリングマシンの同等性は、1937年にアランチューリングによって示されました。チューリングマシンの計算モデルは、命令型プログラミングまたはステートフルプログラミングについて話すときに通常念頭に置いているものであり、ラムダ計算は「純粋な関数型プログラミング」の数学的な形式化です。

すべての効果的な計算モデルは、チューリングマシンと同じ計算を実行でき、その逆も同様であると推測されます。これは、教会チューリング論文と呼ばれます。しかし、この推測は多かれ少なかれ「計算の効果的なモデル」という用語のために証明できません(おそらく誰かが将来新しいモデルを発明するでしょうか?)


2
ツーリングマシンと同等のランバ計算であるため、すべての計算は(多少隠された)状態でなければならないという同じ議論を元に戻すことができます。isがコードの外部(変数による)として表されるか、フローの内部(スタックベースの関数呼び出しによる)として表されるかは常に「状態」です。
エミリオガラヴァリア

3
ラムダ計算には状態があります。その制約は、状態が不変であることです。不変の状態はまだ状態です。ラムダを含む関数のパラメーターはまだ状態です。おそらく、異なるパラメーターが与えられた場合、関数に異なる動作を持たせたいでしょう。
ビリーONeal

@emilio問題に対する同等の状態ベースの解決策があると述べることは(あなたが説明するように)、その解決策のステートレスバージョンが存在しないという証拠ではありません。
ビリーONeal

2
@EmilioGaravagliaでは、ラムダ計算インタープリターの状態を参照しています。ラムダ計算で推論する場合、状態について推論する必要はありません。また、「可変性」の側面も異なります。
ウィルベル

1
@EmilioGaravglia:命令型プログラミングの状態は一度のメモリ構成です。ここでは、パラメータ空間はすべての可能なメモリ値によって与えられ、状態は一度に1つの構成(チューリングマシンの帯域)です。ラムダ計算でプログラムを作成する場合、メモリフィールドなどの直接的なエンティティはありません。プログラムの実行は、ラムダ変換のアプリケーションです。中間ステップは「状態」に似ている場合がありますが、同じ値の単なる同等の表現です。評価中に何も変更されず、式は単に「単純な」形式に書き換えられて処理されます。
ウィルベル

14

どんな動的システムでも、「状態」は、あなたの存在があなたの影響を受けるようにするものです過去または未来の(時間の矢は数学的問題ではなく、単に物理的な制約です)。

「覚えておく」何かを持っているか、それはあなたが何をしたかに依存しますが、あなたは状態を持っています。

状態のないシステムは「動的」ではありません。単なる組み合わせの機能です。それは状態を持たないかもしれませんが、異なる結果を生成するためには、何らかの方法で状態を提供する必要があります。

現在、参照している計算モデルに応じて、状態は明示的に(変数の形式で)または暗黙的に(「リターンアドレス」の形式で)表現できます。

あなたがするとき fna(fnb(x))、fnbに状態が与えられ、fnaの状態が生成されます。これは、xfnbが呼び出される前に存在するという事実によるものです(したがって、それは独自の「過去」に由来します)。

「国家の存在」や「国家が存在しない」問題ではありません。それは「気にする」または「気にしない」のことです。


0

状態とは、現在の刺激だけに基づくのではなく、過去の刺激に依存する方法で現在の刺激に応答する能力を意味します。

純粋に機能的なプログラムは単なる機能です。したがって、実際のアプリケーションでは、純粋に機能的なプログラムはペア(old_state * present_stimulus)を入力し、ペア(new_state * present_response)を出力します。次の刺激を待って状態を伝搬するには、外部のステートフルな「ルーパー」が必要です。

純粋に機能的なプログラムは本質的に状態を持たず、実際のアプリケーションに直接使用することはできません。

したがって状態指向プログラムは、純粋に機能的で状態のない別の実装に置き換えることはできません


0

外の世界と対話する必要がない限り、明示的な可変状態を回避できます。

プログラムで実際にプロセッササイクルを占有する以上の効果を得るには、JavaScriptでDomまたはWindowオブジェクトを変更する必要があり、これらのAPIはステートフルです。ただし、DomおよびWindowオブジェクトをパラメーターとしてJavaScriptコードに渡し、新しいDom / Windowを出力として受け取るラッパーを作成できると思います。これにより、JavaScriptコードが可変状態から分離されます。

もちろん、ブラウザウィンドウとDOMは本質的にステートフルであるため、まだ状態に依存しています。対話型アプリケーションは本質的にステートフルですが、明示的な状態を最小限に抑えるようにコードを構造化できます。

別の質問は、それが良いアイデアかどうかです。設計上純粋な関数型言語であるHaskellでさえ、「状態」モナドが含まれており、これにより可変状態をシミュレートできます。これは、明示的な可変状態が時々望ましいパターンであることを示しています。


0

状態のないプログラミング言語で「状態マシン」をどのように実装するかを考えてください。

おそらく実際に実行できますが、ストレージとして関数名を使用することになります。次のようなgobblyday gookで終わる:

if (sm.atBegining()) sm.start() else if (sm.done()) sm.stop() ) else sm.progress()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.