RustとHaskell:Concordiumのプログラミング言語

Concordiumでは、次世代ブロックチェーンの開発を行っています。これは複雑なソフトウェアであり、正確で信頼性の高いものである必要があります。

Makoto Ota
Nov 23, 2020 · 9 min read

Concordiumは HaskellRustという2つの最前線のプログラミング言語を使用しており、高いクオリティーのコードで生産性を高めることができます。この記事では、なぜこれらの言語を使うのか、どのように使うのかを議論し、選択のメリットとコストを検証していきたいと思います。

HaskellとRustの共通の特徴は、強力で表現力豊かな静的型システムを備えていることです。型システムは値に型を与えます。例えば、Haskellでは 2 は Integer 型を持ち、”Cat” String 型を持ちます。型システムは、2”Cat” を追加するなど、意味のない操作を実行できないようにします。動的型システムは、プログラムが実行されたときにこれを防ぎます;これは、Pythonなどのインタープリター言語で一般的です。静的型システムは、プログラムがコンパイルされたときにこれを防ぎます。Haskellのコンパイラは、2 + “Cat“ を型が正しくないと拒否し、実行時の失敗の可能性を排除します。

もちろん、HaskellとRustの型システムは、整数に文字列を追加することを妨ぐだけではありません。たとえば、Haskellの型システムを使用すると、コードの副作用について明示的にすることができます:これにより、クエリのみを想定したコードでデータベースに書き込むことができなくなります。 Rustの型システムは、メモリの規律を強制します。これにより、lifetimeを超えてメモリにアクセスしたり、安全でない方法でメモリにアクセスしてプログラムをクラッシュさせないようにすることができます。

HaskellとRustの両方に強力な型システムがあるとしたら、なぜ両方を使うのでしょうか?その答えは、両者は他の分野で異なる強みを持っているからです。

Haskell

Haskellは pure で lazy な関数型言語です。関数は、引数や戻り値として他の関数に渡すことができます。関数は部分的に適用して新しい関数を得ることもできます:(+) は2つの整数を足し合わせる関数であり、(1+)1 を別の整数に足す関数です。高階関数 map は、与えられた関数をリストの各要素に適用します:map (1+) [1…4][2,3,4,5] に計算されます。

Lazinessとは、式が評価されるのは、その結果が実際に必要とされるときだけであることを意味します。例えば、take 2 (map (1+) [1…4]) という式を考えてみましょう。これは、map (1+) [1…4] で生成されたリストの最初の2つの要素を取り、結果として [2,3] が得られます。Laziness とは,1+1 1+2 だけが計算されることを意味し,1+3 1+4 は計算されないことを意味します。これにより、コードの実行過程を気にすることなく、コードの意図を表現した優雅で数学的なスタイルでHaskellのコードを書くことが可能になります。

Haskellのlazinessは、コードがより広いコンテキストに依存するため、いつ(そしていつ)評価されるかを予測することが難しいことを意味します。これは、ファイルへの書き込みやネットワーク上での通信などの副作用を持つコードでは問題となりますが、これらの操作の順序を重要と思うからです。

Pureな関数とは、副作用のない関数のことです。Haskellでは、関数はpureです。関数は副作用を持たないので、評価の順番は副作用の順番に影響しません。Haskellでは、monadsを使用することで副作用を可能にしています。monadは、シーケンス化できる計算の概念を捉えています。例えば、IO monadは、コンソールに表示など、外界と相互作用する副作用をカプセル化します。monad内の>>演算子は、monad内の2つのアクションをシーケンスします:print 2 >> print 4 は、最初に2を表示し、次に4を表示します。 (ここでは、monadについてはあまり詳しく説明しません。"monadはburritoのようなものだ"とか、"monadは自己関手の圏の中のmonoidにすぎない"というような記述によって、この概念は初心者のHaskellersには理解しにくいという評判があります。monadの基本的な例題を勉強して、それが一般化にどのように適合するかを見ることをお勧めします。)

Haskellは、多くの高水準言語と同様に、メモリ管理のために garbage collectorに依存しています。実際、メモリ管理はプログラマからはほとんど隠されています:メモリ管理は、評価中に作成された構造体(リストなど)に必要に応じて割り当てられます。構造体は、アクセスできなくなった場合、 garbage collectorによって定期的に解放されます。

明示的に(CやC++のような低水準言語のように)メモリの割り当てや解放を気にしなくてもよいのは便利ですが、Haskellのプログラムは必要以上にメモリを使用してしまい、space leakの原因となります。これは、Haskell のlazinessによって悪化することがよくあります。例えば、ある数値のリストの合計を計算したいとします:lazinessは、プログラムが合計の計算を遅らせてしまい、リスト(これは非常に大きなものになる可能性があります)をgarbage-collectedできないことを意味します。リストではなく合計が必要な場合は、リストをgarbage collectedできるように早めに評価を強制的に行うと便利です。これは、長期間実行されるプログラム(ブロックチェーンノードのようなもの)では特に懸念されることで、累積的なスspace leaksによってプログラムがメモリ不足に陥る可能性があります。Glasgow Haskell Compiler (GHC) は、space leaksの特定と追跡に役立つプロファイリングをサポートしています。しかし、多くの場合、解決策は長く存在しているすべてのデータを強制的に評価することだけです。

Rust

Rustは利便性よりもパフォーマンスを優先します。lazinessやgarbage collectionのような機能はHaskellプログラマに利便性を提供しますが、ランタイムパフォーマンスのコストがかかります。Rustはそのような機能を排除し、代わりに'ゼロコスト抽象化'を採用しています:これは、実行時のコストがほとんどまたはまったくない便利さです。

Rustのメモリ管理へのアプローチは、この典型的な例です。Rustはgarbage collectorを使用していませんが、ownershiplifetimesを使用することで、プログラマは明示的なメモリ管理から大きく解放されます。Rustの型システムはデータ構造が最後に使用された場所を決定し、コンパイラはその時点でそれを解放するためのコードを自動的に生成します。例えば、ベクターが関数の引数として渡された場合、その関数はベクターのownershipを引き継ぎ、ベクターのownershipを渡さなかった場合は、その関数はlifetimeの終了時にベクターを解放します。lifetime解析は無償では一方、その費用はコンパイル時に全額負担します。

Concordiumのコンビネーション

RustとHaskellの異なる哲学は、両者に異なる強みを与えています。Rustは低水準のパフォーマンスークリティカルなコードに適していますが、Haskellは高水準の正当性ークリティカルなコードに適しています。Concordiumでは、それぞれの強みを生かすようにしています。暗号プリミティブとアイデンティティ・レイヤーにはRustを使用しており、計算量が多くパフォーマンスが重要なものとなっています。コンセンサス、トランザクション・スケジューラ、スマートコントラクト言語の実装にはHaskellを使用しています。

2つのプログラミング言語を使用することで、それぞれの長所を活かすことができますが、HaskellとRustの間のインターフェースがシームレスではないという欠点があります。言語の外部関数インタフェース(FFI)は、他の言語で書かれたコードと相互運用するための手段を提供します。FFIは一般的にC言語を念頭に置いて設計されており、ある言語から別の言語にデータを渡す方法を制限しています。(複雑な例として、Rust のポインタが C のポインタと同じサイズであるとは限りません。WindowsではクラッシュしてもLinuxではクラッシュしないコードがあることを発見しました)。2 つの言語を使用すると、複数のコンパイラの出力をリンクする必要があるため、ビルドプロセスが複雑になります。これは複数のオペレーティングシステムを使用している場合にはさらに悪化します。

最終的には、RustとHaskellは、強力で表現力豊かな型システム、強力な抽象化メカニズム(RustのトレイトとHaskellの型クラス)、型付きメタプログラミング(RustのmacrosとHaskellのTemplateを介して)、優れたコンパイラ(rustcとghc)を備えた最前線の言語です。これらの機能により、Concordium は効率的で信頼性の高いブロックチェーンソフトウェアの開発の最先端に立つことができます。

Concordium-Japan

アイデンティティ識別機能ブロックチェーンプラットフォーム

Concordium-Japan

ビジネスアプリケーションにフォーカスして設計された、規制要件を満たすためにプロトコルにアイデンティティ識別機能を組み込んだ、パーミッションレスのブロックチェーンプラットフォームを提供しています。

Makoto Ota

Written by

Currently as Japan Lead at Concordium Foundation building an identity built-in consensus mechanism Blockchain platform.

Concordium-Japan

ビジネスアプリケーションにフォーカスして設計された、規制要件を満たすためにプロトコルにアイデンティティ識別機能を組み込んだ、パーミッションレスのブロックチェーンプラットフォームを提供しています。

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store