Ответ 1
Вы не можете избавиться от побочных эффектов при выполнении IO
-operations, поэтому здесь нет хороших функциональных способов. Все функциональные вещи фактически заканчиваются, когда вы начинаете взаимодействовать с пользователем/устройствами напрямую, никакая монада не может помочь вам сделать один внешний побочный эффект; однако, вы можете описать (обернуть) последовательные побочные эффекты, используя монады IO -like.
Говоря о вашем примере, рестайлинговый код может выглядеть так:
implicit class FileMonads(f: File) {
def check = if (f.exists) Some(f) else None //returns "Maybe" monad
def remove = if (f.delete()) Some(f) else None //returns "Maybe" monad
}
for {
foundFile <- new File(path).check
deletedFile <- foundFile.remove
} yield deletedFile
res11: Option[java.io.File] = None
Но это слишком многословно без каких-либо реальных преимуществ, если вы просто хотите удалить один файл. Более того, проверка fileTemp.exists
не имеет смысла и на самом деле не надежна (как указывал @Eduardo). Итак, даже в Scala лучший способ, который я знаю, это FileUtils.deleteQuietly:
FileUtils.deleteQuietly(new File(path))
Или даже
new File(path).delete()
Он не выдаст исключение для несуществующего файла - просто верните false
.
Если вы действительно хотите что-то более Scala-way - посмотрите на rapture.io, например:
val file = uri"file:///home/work/garbage"
file.delete()
Или скалао. Подробнее: Как сделать создание файлов и манипулирование ими в функциональном стиле?
PS Однако IO-монады могут быть полезны (в отличие от Some/None в моем случае), когда вам требуются асинхронные операции, поэтому наивный код (без cats/scalaz) будет выглядеть так:
implicit class FileMonads(f: File) {
def check = Future{ f.exists } //returns "Future" monad
def remove = Future{ f.remove } //returns "Future" monad
}
for {
exists <- new File(path).check
_ <- if (exists) foundFile.remove else Future.unit
}
Конечно, в реальном мире лучше всего использовать некоторые NIO-оболочки, такие как FS2-io: https://lunatech.com/blog/WCl5OikAAIrvQCoc/functional-io-with-fs2-streams