Functional Programming in Scalaの第6章を読んで状態モナドを理解しようとしたら、副作用クラスをラップすることについて質問があります。副作用のあるクラスをラップする
いいえ、私は多分自分自身を変更するクラスがあります。
class SideEffect(x:Int) {
var value = x
def modifyValue(newValue:Int):Unit = { value = newValue }
}
私の理解では、私たちは以下のようStateモナドでこれを包んだ場合、それはまだ議論の余地がそれを包むのポイントを作る元を変更するだろうということです。
case class State[S,+A](run: S => (A, S)) { // See footnote
// map, flatmap, unit, utility functions
}
val sideEffect = new SideEffect(20)
println(sideEffect.value) // Prints "20"
val stateMonad = State[SideEffect,Int](state => {
state.modifyValue(10)
(state.value,state)
})
stateMonad.run(sideEffect) // run the modification
println(sideEffect.value) // Prints "10" i.e. we have modified the original state
私が見ることができるこの唯一の解決策は、クラスのコピーを作成し、それを修正することであるが、それはSideEffectの成長に合わせて計算コストが高いようです。さらに、Cloneableを実装していないJavaクラスのようなものをラップしたい場合は、不運になります。
val stateMonad = State[SideEffect,Int](state => {
val newState = SideEffect(state.value) // Easier if it was a case class but hypothetically if one was, say, working with a Java library, one would not have this luxury
newState.modifyValue(10)
(newState.value,newState)
})
stateMonad.run(sideEffect) // run the modification
println(sideEffect.value) // Prints "20", original state not modified
State Monadを間違って使用していますか?副作用クラスをコピーせずにラップする方法、またはこれが唯一の方法ですか?
- 私はここで使用しているStateモナドのための実装は本からなり、Scalazの実装は異なる場合がありますあなたは、いくつかの変異を隠す以外可変オブジェクトと何もできない