Как сделать эффективные вычисления ссылочными прозрачными - PullRequest
0 голосов
/ 30 мая 2018

Я учу FP, написав простые приложения.И сейчас я подхожу к эффекту монады (cats.effect.IO / scalaz.IO не имеет большого значения).У меня есть две функции:

def open(path: String): IO[InputStream] = IO {
  new FileInputStream(new File(path))
}

def read(is: InputStream): IO[Option[Array[Byte]]] = IO {
  val buffer = new Array[Byte](4096)
  val bytesRead = is.read(buffer)
  if (bytesRead != -1) {
    val newBuffer = new Array[Byte](bytesRead)
    System.arraycopy(buffer, 0, newBuffer, 0, bytesRead)
    print(new String(buffer))
    Some(newBuffer)
  }
  else
    None
}

И я могу объединить их в поток следующим образом

import cats.effect.IO
import fs2.Stream

object App {

    def main(args: Array[String]): Unit = logic.unsafeRunSync()

    def logic: IO[Unit] = for {
      is <- open("/tmp/prompthooks.py")
      _ <- fs2.Stream.eval(read(is)).repeat.unNoneTerminate.compile.drain
    } yield ()
}

И это прекрасно работает.Но вопрос в том, все ли это реализовано в чистом FP.У меня есть сомнения по этому поводу в том смысле, что def read(is: InputStream): IO[Option[Array[Byte]] принимает поток и пытается читать с него.Да, это приостанавливает побочный эффект, но в val io = read(is) это своего рода состояние (если мы выполним unsafeRunSync дважды, мы получим другой результат.

...