Недавно я просмотрел видео о том, как вы могли прийти к монаде 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()
}
}
Вы можете видеть, как эффекты откладываются до тех пор, пока не станет основной. Я придумал это после того, как почувствовал это из видео.
Является ли моя реализация правильной и правильно ли я понимаю.
Мне также интересно, следует ли использовать milage, он должен быть объединен с ValidationMonad, как в ValidationMonad [IO [Person]], чтобы мы могли коротко замыкаться, когда происходят исключения? Мысли, пожалуйста.
Blair