ドン・スチュワートが正しく指摘したように、あなたは状態モナドではなく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です。
"ハスケルでは、このようなモナドを使用するのは、命令的アルゴリズムを効率的に実装する唯一の方法だと思います。 - それは間違っています。状態モナドはシンプルで純粋に機能的なモナドですが、メモリ効果のネイティブハードウェアサポートではSTモナドを使用します。任意の副作用の場合、IOモナド。おそらくあなたはScalaのSTモナドを探しているでしょうか? –
@DonStewartそうです。私はいつも名前の混乱を見つけました。 – ziggystar