最近、IO モナドを思いつく方法についてのビデオを見ましたが、話は scala で行われていました。私は実際、関数が IO[A] を返すポイントが何であるか疑問に思っています。IO オブジェクトにラップされたラムダ式は、ミューテーションとは何かであり、何かが起こるように、それらが監視されなければならない、つまり実行されなければならない変更のより高い時点でです。問題を別の場所に押し上げているだけではありませんか?
私が見ることができる唯一の利点は、unsafePerformIO 操作を呼び出さなければ副作用が発生しないという意味で、遅延評価が可能になることです。また、プログラムの他の部分がコードを使用/共有し、副作用を発生させたいときに判断できると思います。
これだけなのかな?と思いました。テスト容易性に利点はありますか?これを否定する効果を観察する必要があるため、そうではないと思います。特性/インターフェースを使用した場合、依存関係を制御できますが、これらの依存関係で効果が発生するタイミングは制御できません。
次の例をコードにまとめました。
case class IO[+A](val ra: () => A){
def unsafePerformIO() : A = ra();
def map[B](f: A => B) : IO[B] = IO[B]( () => f(unsafePerformIO()))
def flatMap[B](f: A => IO[B]) : IO[B] = {
IO( () => f(ra()).unsafePerformIO())
}
}
case class Person(age: Int, name: String)
object Runner {
def getOlderPerson(p1: Person,p2:Person) : Person =
if(p1.age > p2.age)
p1
else
p2
def printOlder(p1: Person, p2: Person): IO[Unit] = {
IO( () => println(getOlderPerson(p1,p2)) ).map( x => println("Next") )
}
def printPerson(p:Person) = IO(() => {
println(p)
p
})
def main(args: Array[String]): Unit = {
val result = printPerson(Person(31,"Blair")).flatMap(a => printPerson(Person(23,"Tom"))
.flatMap(b => printOlder(a,b)))
result.unsafePerformIO()
}
}
私がクールだと思うメインまで効果がどのように延期されるかを見ることができます。動画で感じたので思いつきました。
私の実装は正しいですか、私の理解は正しいですか。
ValidationMonad[IO[Person]] のように、ValidationMonad と組み合わせて、例外が発生したときに短絡できるようにする必要があるかどうかも疑問に思っています。考えてください。
ブレア