2013-10-29 12 views
7

Scalazは、ステートフルな計算より優れた抽象化を提供します:STモナド。ScalaでSTモナドを使用するタイミングは?

STモナドは、機能的な形で副作用を計算することを可能にします。

ハスケルでは、このようなモナドを使用することが、いくつかの命令的アルゴリズムを効率的に実装する唯一の方法だと思います。

しかし、Scalaでは、必要に応じて簡単に変更可能なデータ構造を使用できます。

私が知ったのは、Scalazの機能概念には計算上のオーバーヘッドがあるということです。たとえばthis questionを参照してください。したがって、所望の目標が効率の向上である場合、STモナドを使用して、機能的な実装から機能的な実装に切り替えることは合理的ではないように思われる。私が求めている何

はこのようです:

  • STモナドを使用することが合理的である場合には?
  • あなたはそれをどのような状況で使用しましたか?良い選択であると思われますか?
+1

"ハスケルでは、このようなモナドを使用するのは、命令的アルゴリズムを効率的に実装する唯一の方法だと思います。 - それは間違っています。状態モナドはシンプルで純粋に機能的なモナドですが、メモリ効果のネイティブハードウェアサポートではSTモナドを使用します。任意の副作用の場合、IOモナド。おそらくあなたはScalaのSTモナドを探しているでしょうか? –

+0

@DonStewartそうです。私はいつも名前の混乱を見つけました。 – ziggystar

答えて

11

ドン・スチュワートが正しく指摘したように、あなたは状態モナドではなくSTモナドを探しているようです。だから私の答えはそれについてだ。

STモナドは、通常は変更が許可されていないHaskellでローカルの変更を許可するために使用されます。たとえば、命令語sumを記述したい場合は、STモナドを使用します。 scalazと、このような機能の一例(hereから取られた)ことになります。

def sumST[S, A](as: List[A])(implicit A: Numeric[A]): ST[S, A] = 
    for { n <- newVar(A.zero) 
     _ <- as.traverseU(a => n.mod(A.plus(_, a))) 
     m <- n.read } yield m 

def sum[A : Numeric](as: List[A]): A = 
    runST(new Forall[({type λ[S] = ST[S, A]})#λ] { 
    def apply[S] = sumST[S, A](as) 
    }) 

もちろんScalaで、我々はまた、単に書くことができます:

def sum[A](xs: List[A])(implicit N: Numeric[A]) = { 
    var sum = N.zero 
    val it = xs.iterator 
    while (it.hasNext) { 
    sum = N.plus(sum, it.next) 
    } 
    sum 
} 

これはまだ可変状態として、参照透明になります関数のスコープをエスケープします。ハスケルでは、このような場合に使用されます。なぜなら、我々は単純にvarを持つことができないからです。

なぜSTをスカラーで使用するのですか? (配列のような)可変構造に取り組み、この可変構造が計算の範囲をエスケープするのではなく、まず不変のものに変えなければならないことを保証したい場合は、STを使用することができます。スカラズではこのような場合にSTArrayがあり、STモナドの実行時にImmutableArrayになります。その良い例はbinary sort example in scalazです。読む価値があるのはRúnarBjarnasonのblog article on ST monadです。

+0

ローカルの可変状態を使用するためにあなたの例でforループを使用していないのはなぜですか?パフォーマンス? –

+0

はい、変更可能な状態を閉じるのを避けるためです。 – drexin

関連する問題