web-dev-qa-db-ja.com

一部の関数型言語にソフトウェアトランザクションメモリが必要なのはなぜですか?

関数型言語は、定義上、状態変数を維持するべきではありません。では、なぜHaskellやClojureなどがソフトウェアトランザクションメモリ(STM)実装を提供するのでしょうか。 2つのアプローチの間に矛盾はありますか?

24
Michael Spector

可変状態を維持する関数型言語に問題はありません。 Haskellなどの「純粋な」関数型言語でさえ、現実の世界と対話するために状態を維持する必要があります。 Clojureのような「不純な」関数型言語は、状態の変化を含む可能性のある副作用を許容します。

重要な点は、関数型言語は、本当に必要な場合を除いて、可変状態を阻止することです。一般的なスタイルは、純粋な関数と不変データを使用してプログラミングし、それを必要とするコードの特定の部分で「不純な」可変状態のみと対話することです。そうすれば、コードベースの残りの部分を「純粋」に保つことができます。

STMが関数型言語でより一般的である理由はいくつかあると思います。

  • Research:STMはホットな研究トピックであり、プログラミング言語の研究者は関数型言語(それ自体が研究トピックであることに加えて、プログラムの動作に関する「証明」を作成する)
  • ロックは構成しません:STMは、並行性に対するロックベースのアプローチの代替手段と見なすことができます。異なるコンポーネントを組み合わせることで複雑なシステム。これは間違いなくSTMの「実用的な」主な理由です
  • STMは不変性に適しています:不変構造が大きい場合、不変のままであることを確認したいので、他のスレッドは必要ありません入って来て、いくつかのサブエレメントを変更します。同様に、上記のデータ構造の不変性を保証できる場合は、STMシステムでを安定した「値」として確実に扱うことができます。

私は個人的には可変性を許可するClojureのアプローチが好きですが、STMトランザクションに参加する可能性がある厳密に制御された「管理された参照」のコンテキストでのみです。言語の他のすべては「純粋に機能的」です。

  ;; define two accounts as managed references
  (def account-a (ref 100))
  (def account-b (ref 100))

  ;; define a transactional "transfer" function
  (defn transfer [ref-1 ref-2 amount]
    (dosync
      (if (>= @ref-1 amount)
        (do 
          (alter ref-1 - amount)
          (alter ref-2 + amount))
        (throw (Error. "Insufficient balance!")))))

  ;; make a stranfer
  (transfer account-a account-b 75)

  ;; inspect the accounts
  @account-a
  => 25

  @account-b
  => 175

上記のコードは完全にトランザクション的でアトミックです。別のトランザクション内の2つのバランスを読み取る外部オブザーバーは常に一貫したアトミック状態を参照します。つまり、2つのバランスの合計は常に200になります。ロックベースの同時実行では、これは驚くほど難しい問題です。多くのトランザクションエンティティを持つ大規模で複雑なシステムで解決する。

いくつかの追加の啓蒙のために、リッチヒッキーは このビデオでClojureのSTMを説明する優れた仕事 を行います

13
mikera

関数型言語は、定義により、状態変数を維持すべきではありません

あなたの定義は間違っています。状態を維持できない言語は使用できません。

関数型言語と命令型言語の違いは、一方が状態を持ち、もう一方が状態を持たないことではありません。それは彼らが状態を維持する方法にあります。

命令型言語は、プログラム全体に州が広がっています。

関数型言語は、型シグネチャによって明示的に状態を分離し、維持します。そしてそれが、STMのような高度な状態管理メカニズムを提供する理由です。

3
Vagif Verdi

場合によっては、プログラムが変更可能な状態(たとえば、Webアプリのデータベースの内容)を必要とし、関数型プログラミングの benefits を失うことなくそれを使用できることは素晴らしいことです。非関数型言語では、変更可能な状態がすべてに浸透します。なんらかの 特別なAPI を使用してそれを明示的にすると、他のすべてが純粋に機能している間、それを小さな識別可能な領域に制限できます。 FPの利点には、デバッグの容易さ、繰り返し可能な単体テスト、無痛の同時実行性、マルチコア/ GPUの使いやすさが含まれます。

2
Will Ware