プルーフベースのプログラミングとは、テストせずにプログラムの正しさをなんとかして証明できることを意味します。
エイダにはコントラクトという機能があると聞きましたが、ハスケルのタイプチェッカーに合格できれば、プログラムはおそらく正しいと聞きました。
これらの2つの言語で1行のテストコードなしで正しいプログラムを書くことはできますか?この種の機能をサポートする他の言語はありますか?
あなたが何を求めているのかは正確には明確ではありません。
必要に応じて、いつでもプログラムが正しいことを証明できます。これは言語に依存しません。
問題は、コンピュータに証明を行わせることができるか、または少なくともチェックあなたから与えられた証明を行うことができるかということです。そして答えは:はい!
実際、Curry-Howard-Isomorphismは、論理とプログラミングの間、証明とプログラムの間、定理と型の間には同型があると述べています。すべてのタイプは定理(およびその逆)であり、すべてのプログラムは証明(およびその逆)です。したがって、ある意味で、すべての静的型付け言語がこれを行います。すべての型チェッカーは定理の証明者です!
ただし、型で表現できるものには制限があります。 Haskellを使用すると、たとえばJavaよりも多くのことを表現できますが、さらに多くのことが可能です。依存型の言語では、静的型は実行時の値に依存する場合があります。たとえば、n
要素を持つリストであるタイプList<n>
が存在する可能性があります。ここで、n
は実行時にのみ決定される値です。
さて、そのようなプログラムをタイプチェックするためには、タイプチェッカーがランタイム値に関するプロパティを静的に証明できる必要がありますが、これにより停止問題にすばやく遭遇することは誰もが知っています。まあ、依存型付けされた言語には簡単な解決策があります:それらは非終了を許可せず、それらはtotal、すなわちalwaysは終了するため、停止性問題は適用されません。
明らかに、それはチューリング完全ではないことを意味しますが、それは実際よりも恐ろしいように聞こえます。まず、チューリング完全ではないがまだ有用な言語がたくさんあります。正規表現、SQL(2003より前)、HTML + CSS(HTML5 + CSS3より前)などです。実際、C仕様では、オブジェクトのアドレスとオブジェクトのサイズを取得できることが必要であり、これらは両方とも有限サイズの整数に収まる必要があるため、Cは厳密にはチューリング完全ではありません。無限のメモリを持っています。同様に、私たちのコンピューターもチューリング完全ではありません。実際、チューリング完全なコンピューティングマシンを構築することは物理的に不可能です。
しかし、それは髪の毛を分割することであり、はるかに実用的な考慮事項があります。たとえば、オペレーティングシステム、Webサーバー、またはイベントループのあるものは、チューリング完全でない言語では構築できないと考えるかもしれません。しかし、たとえばオペレーティングシステムをデータの無限ループ(またはむしろ無限再帰)としてモデル化する代わりに、finiteを使用してモデル化することもできます。 -)co-dataに対するco-recursion!そして実際、問題にはそのようなパターンがたくさんあり、一見すると無限ループまたは非終了の再帰が必要になる場合があります。
依存型付けされた言語は、3つの広い範囲に分類されます。
これらの言語/証明システムのいくつかは(順不同)です。
それらの中で、Coqは最も成熟しています。ただし、明らかにプログラミング用に設計されたものではありません。プログラミング言語として見たとき、それは実際にはとてもいいものではありません。
OTOH、イドリスは少し新しいですが、明らかにプログラミング言語として設計されています。 Haskellにとてもよく似ています。あなたはそれを依存型を持つHaskellと考えることができます。
ATSは他とは異なります。完全な依存型の言語/証明アシスタントではありません。むしろ、システムプログラミング言語として、C、C++、D、Java、C#などの言語の代わりとして、Cに匹敵するパフォーマンスを備え、「いくつかの興味深いプロパティを証明するのに十分な依存型」として設計されています。 ATSは、すべてを証明できるようにすることを目的としていませんが、オペレーティングシステム、コンパイラ、サーバーなどのソフトウェアシステムの特定の安全特性を証明することを目的としています。
いくつかの考え:
証明は、コードで何を達成したいかを知りません。これは、適切に記述されたソフトウェア要件の領域です。
テスト(TDDのように要件の説明として使用される場合)は、ソフトウェア自体ではなく、ソフトウェア要件の証明です。
証明は、実際のプログラムの複雑さを超える可能性があり、多くの場合、それを超えます。証明は、テストとは異なり、考えられるすべてのエッジケースを考慮する必要があります。
証明または予測できないものがいくつかあります。お客様が「これは私が実際に望んでいたものではない」と言っているようなものです。
そうは言っても、Haskellはおそらく「証明によるプログラミング」に最も近いものです。
優れた言語設計者(および優れたプログラマー)は、鉄壁の保証を求めるのではなく、複雑さを可能な限り減らすことによってソフトウェアの信頼性を高めようとします。これにより、エッジケースの数が減少します(ただし、排除はされません)。