From 5413060842220c4894a0aac096e08a5a4024c515 Mon Sep 17 00:00:00 2001 From: handlessmidas Date: Fri, 8 May 2020 17:57:42 +0500 Subject: [PATCH 1/2] lab8 --- .gitignore | 16 ++++++ build.sbt | 9 ++++ project/build.properties | 1 + src/main/scala/main.scala | 104 ++++++++++++++++++++++++++++++++++++++ src/test/scala/test.scala | 44 ++++++++++++++++ 5 files changed, 174 insertions(+) create mode 100644 build.sbt create mode 100644 project/build.properties create mode 100644 src/main/scala/main.scala create mode 100644 src/test/scala/test.scala diff --git a/.gitignore b/.gitignore index 9c07d4a..349cac9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,18 @@ *.class *.log + +# sbt specific +.cache/ +.history/ +.lib/ +dist/* +target/ +lib_managed/ +src_managed/ +project/boot/ +project/plugins/project/ + +# Scala-IDE specific +.scala_dependencies +.worksheet +.idea \ No newline at end of file diff --git a/build.sbt b/build.sbt new file mode 100644 index 0000000..f7730b7 --- /dev/null +++ b/build.sbt @@ -0,0 +1,9 @@ +name := "ScalaLabs" + +version := "0.1" + +scalaVersion := "2.12.11" + +libraryDependencies += "org.typelevel" %% "cats-core" % "2.0.0" + +libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.1" % "test" diff --git a/project/build.properties b/project/build.properties new file mode 100644 index 0000000..f37b0aa --- /dev/null +++ b/project/build.properties @@ -0,0 +1 @@ +sbt.version = 1.3.10 \ No newline at end of file diff --git a/src/main/scala/main.scala b/src/main/scala/main.scala new file mode 100644 index 0000000..2b5e14e --- /dev/null +++ b/src/main/scala/main.scala @@ -0,0 +1,104 @@ +import java.nio.file.{Files, Path, Paths, StandardCopyOption} + +import cats.data.{IndexedStateT, StateT} +import cats.{Applicative, Functor, Id, Monad} +import cats.syntax.all._ +import cats.instances.list._ + +import scala.language.higherKinds + +import scala.collection.JavaConverters._ + +trait MkDir[F[_], Dir] { + def mkDir(dir: Dir, name: String): F[Dir] +} + +trait MkFile[F[_], Dir, File] { + def mkFile(dir: Dir, name: String): F[File] +} + +trait Printer[F[_], File] { + def printName(file: File): F[Unit] +} + +trait GetFiles[F[_], Dir, File] { + def getFiles(dir: Dir): F[List[File]] +} + +trait GetFileName[F[_], File]{ + def getFileName(file: File): F[String] +} + +trait MoveFile[F[_], Dir, File] { + def moveFile(file: File, dest: Dir): F[File] +} + +class Program[F[_], Dir, File](implicit + F: Monad[F], + mkDir: MkDir[F, Dir], + mkFile: MkFile[F, Dir, File], + printer: Printer[F, File], + getFiles: GetFiles[F, Dir, File], + getFileName: GetFileName[F, File], + moveFile: MoveFile[F, Dir, File]) { + def run(dir: Dir, dirName: String, fileNames: List[String]): F[Unit] = for { + newDir <- mkDir.mkDir(dir, dirName) + _ <- fileNames.traverse(name => mkFile.mkFile(newDir, name)) + files <- getFiles.getFiles(newDir) + _ <- files.traverse(file => printer.printName(file)) + names <- files.traverse(file => getFileName.getFileName(file)) + letters = names.map(_.head) + dirs <- letters.traverse(letter => mkDir.mkDir(newDir, letter.toString)) + _ <- files.zip(dirs).traverse(p => moveFile.moveFile(p._1, p._2)) + } yield () +} + +class RealFileSystem[F[_] : Applicative] extends MkDir[F, Path] with MkFile[F, Path, Path] + with GetFiles [F, Path, Path] with GetFileName[F, Path] with MoveFile [F, Path, Path] { + + override def moveFile(file: Path, dest: Path): F[Path] = { + Files.move(file, dest.resolve(file.getFileName), StandardCopyOption.REPLACE_EXISTING).pure[F] + } + + override def getFileName(file: Path): F[String] = { + file.getFileName.toString.pure[F] + } + + override def getFiles(dir: Path): F[List[Path]] = { + Files.list(dir).filter(Files.isRegularFile(_)).iterator().asScala.toList.pure[F] + } + + override def mkDir(dir: Path, name: String): F[Path] = { + if (Files.exists(dir.resolve(name))) { + dir.resolve(name).pure[F] + } else { + Files.createDirectories(dir.resolve(name)).pure[F] + } + } + + override def mkFile(dir: Path, name: String): F[Path] = { + if (Files.exists(dir.resolve(name))) { + dir.resolve(name).pure[F] + } else { + Files.createFile(dir.resolve(name)).pure[F] + } + } +} + + class ConsoleRealPrinter[F[_] : Applicative] extends Printer[F, Path] { + override def printName(file: Path): F[Unit] = println(file.getFileName).pure[F] + } + +object TypeClasses { + def main(args: Array[String]): Unit = { + + implicit val fs: RealFileSystem[Id] = new RealFileSystem[Id] + implicit val printer: ConsoleRealPrinter[Id] = new ConsoleRealPrinter[Id] + val program = new Program[Id, Path, Path] + + program.run(Paths.get("."), "test_dir", List("foo", "bar", "baz")) + } +} + + + diff --git a/src/test/scala/test.scala b/src/test/scala/test.scala new file mode 100644 index 0000000..3db1f6d --- /dev/null +++ b/src/test/scala/test.scala @@ -0,0 +1,44 @@ +import java.nio.file.{Files, Path, Paths} +import java.util.Comparator + +import cats.Id +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + + +class test extends AnyFlatSpec with Matchers { + val root: Path = Paths.get("./tmp") + Files.createDirectory(root) + + implicit val fs: RealFileSystem[Id] = new RealFileSystem[Id] + implicit val printer: ConsoleRealPrinter[Id] = new ConsoleRealPrinter[Id] + val program = new Program[Id, Path, Path] + + program.run(root, "test_dir", List("foo", "bar", "baz")) + + var dir: Path = root.resolve("test_dir") + + Files.exists(dir) shouldBe true + + var fDir: Path = dir.resolve("f") + var bDir: Path = dir.resolve("b") + + Files.exists(fDir) shouldBe true + Files.isDirectory(fDir) shouldBe true + Files.exists(bDir) shouldBe true + Files.isDirectory(bDir) shouldBe true + + val foo: Path = fDir.resolve("foo") + val bar: Path = bDir.resolve("bar") + val baz: Path = bDir.resolve("baz") + + Files.exists(foo) shouldBe true + Files.isRegularFile(foo) shouldBe true + Files.exists(bar) shouldBe true + Files.isRegularFile(bar) shouldBe true + Files.exists(baz) shouldBe true + Files.isRegularFile(baz) shouldBe true + + Files.walk(root).sorted(Comparator.reverseOrder()) + .forEach(file => Files.deleteIfExists(file)) +} \ No newline at end of file From 53cae0f2e4542480b7b4a390fc807dc5255316b7 Mon Sep 17 00:00:00 2001 From: handlessmidas Date: Fri, 8 May 2020 19:16:16 +0500 Subject: [PATCH 2/2] lab10 --- build.sbt | 14 +++-- src/main/scala/CatsEffect.scala | 39 ++++++++++++ src/main/scala/main.scala | 104 -------------------------------- src/test/scala/test.scala | 44 -------------- 4 files changed, 49 insertions(+), 152 deletions(-) create mode 100644 src/main/scala/CatsEffect.scala delete mode 100644 src/main/scala/main.scala delete mode 100644 src/test/scala/test.scala diff --git a/build.sbt b/build.sbt index f7730b7..d36719d 100644 --- a/build.sbt +++ b/build.sbt @@ -1,9 +1,15 @@ name := "ScalaLabs" -version := "0.1" +version := "1.0" -scalaVersion := "2.12.11" +scalaVersion := "2.12.8" -libraryDependencies += "org.typelevel" %% "cats-core" % "2.0.0" +libraryDependencies += "org.typelevel" %% "cats-effect" % "1.3.0" withSources() withJavadoc() -libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.1" % "test" +scalacOptions ++= Seq( + "-feature", + "-deprecation", + "-unchecked", + "-language:postfixOps", + "-language:higherKinds", + "-Ypartial-unification") \ No newline at end of file diff --git a/src/main/scala/CatsEffect.scala b/src/main/scala/CatsEffect.scala new file mode 100644 index 0000000..468e1a4 --- /dev/null +++ b/src/main/scala/CatsEffect.scala @@ -0,0 +1,39 @@ +import cats.CommutativeApply.ops.toAllCommutativeApplyOps +import cats.syntax.all._ +import cats.instances.list._ +import cats.effect._ +import cats.effect.concurrent.{MVar, Ref, Semaphore} +import scala.concurrent.duration._ +import scala.concurrent.ExecutionContext + + +object CatsEffect extends IOApp { + + def runPrinter(mVar: MVar[IO, String]): Resource[IO, Unit] = { + def rec: IO[Unit] = for { + value <- mVar.take + _ <- IO(println(value)) + _ <- rec + } yield () + + Resource.make(rec.start)(_.cancel.flatMap(_ => IO(println("Printer closed")))).void + } + + def runCounter(mVar: MVar[IO, String]): Resource[IO, Unit] = { + def rec(counter: Int): IO[Unit] = for { + _ <- mVar.put((counter).toString) + _ <- IO.sleep(1.seconds) + _ <- rec(counter + 1) + } yield () + + Resource.make(rec(0).start)(_.cancel.flatMap(_ => IO(println("Counter closed")))).void + } + + val runProgram: Resource[IO, Unit] = for { + mVar <- Resource.make(MVar.empty[IO, String])(_ => IO(print(""))) + _ <- runPrinter(mVar) + _ <- runCounter(mVar) + } yield() + + override def run(args: List[String]): IO[ExitCode] = runProgram.use(_ => IO.never) +} diff --git a/src/main/scala/main.scala b/src/main/scala/main.scala deleted file mode 100644 index 2b5e14e..0000000 --- a/src/main/scala/main.scala +++ /dev/null @@ -1,104 +0,0 @@ -import java.nio.file.{Files, Path, Paths, StandardCopyOption} - -import cats.data.{IndexedStateT, StateT} -import cats.{Applicative, Functor, Id, Monad} -import cats.syntax.all._ -import cats.instances.list._ - -import scala.language.higherKinds - -import scala.collection.JavaConverters._ - -trait MkDir[F[_], Dir] { - def mkDir(dir: Dir, name: String): F[Dir] -} - -trait MkFile[F[_], Dir, File] { - def mkFile(dir: Dir, name: String): F[File] -} - -trait Printer[F[_], File] { - def printName(file: File): F[Unit] -} - -trait GetFiles[F[_], Dir, File] { - def getFiles(dir: Dir): F[List[File]] -} - -trait GetFileName[F[_], File]{ - def getFileName(file: File): F[String] -} - -trait MoveFile[F[_], Dir, File] { - def moveFile(file: File, dest: Dir): F[File] -} - -class Program[F[_], Dir, File](implicit - F: Monad[F], - mkDir: MkDir[F, Dir], - mkFile: MkFile[F, Dir, File], - printer: Printer[F, File], - getFiles: GetFiles[F, Dir, File], - getFileName: GetFileName[F, File], - moveFile: MoveFile[F, Dir, File]) { - def run(dir: Dir, dirName: String, fileNames: List[String]): F[Unit] = for { - newDir <- mkDir.mkDir(dir, dirName) - _ <- fileNames.traverse(name => mkFile.mkFile(newDir, name)) - files <- getFiles.getFiles(newDir) - _ <- files.traverse(file => printer.printName(file)) - names <- files.traverse(file => getFileName.getFileName(file)) - letters = names.map(_.head) - dirs <- letters.traverse(letter => mkDir.mkDir(newDir, letter.toString)) - _ <- files.zip(dirs).traverse(p => moveFile.moveFile(p._1, p._2)) - } yield () -} - -class RealFileSystem[F[_] : Applicative] extends MkDir[F, Path] with MkFile[F, Path, Path] - with GetFiles [F, Path, Path] with GetFileName[F, Path] with MoveFile [F, Path, Path] { - - override def moveFile(file: Path, dest: Path): F[Path] = { - Files.move(file, dest.resolve(file.getFileName), StandardCopyOption.REPLACE_EXISTING).pure[F] - } - - override def getFileName(file: Path): F[String] = { - file.getFileName.toString.pure[F] - } - - override def getFiles(dir: Path): F[List[Path]] = { - Files.list(dir).filter(Files.isRegularFile(_)).iterator().asScala.toList.pure[F] - } - - override def mkDir(dir: Path, name: String): F[Path] = { - if (Files.exists(dir.resolve(name))) { - dir.resolve(name).pure[F] - } else { - Files.createDirectories(dir.resolve(name)).pure[F] - } - } - - override def mkFile(dir: Path, name: String): F[Path] = { - if (Files.exists(dir.resolve(name))) { - dir.resolve(name).pure[F] - } else { - Files.createFile(dir.resolve(name)).pure[F] - } - } -} - - class ConsoleRealPrinter[F[_] : Applicative] extends Printer[F, Path] { - override def printName(file: Path): F[Unit] = println(file.getFileName).pure[F] - } - -object TypeClasses { - def main(args: Array[String]): Unit = { - - implicit val fs: RealFileSystem[Id] = new RealFileSystem[Id] - implicit val printer: ConsoleRealPrinter[Id] = new ConsoleRealPrinter[Id] - val program = new Program[Id, Path, Path] - - program.run(Paths.get("."), "test_dir", List("foo", "bar", "baz")) - } -} - - - diff --git a/src/test/scala/test.scala b/src/test/scala/test.scala deleted file mode 100644 index 3db1f6d..0000000 --- a/src/test/scala/test.scala +++ /dev/null @@ -1,44 +0,0 @@ -import java.nio.file.{Files, Path, Paths} -import java.util.Comparator - -import cats.Id -import org.scalatest.flatspec.AnyFlatSpec -import org.scalatest.matchers.should.Matchers - - -class test extends AnyFlatSpec with Matchers { - val root: Path = Paths.get("./tmp") - Files.createDirectory(root) - - implicit val fs: RealFileSystem[Id] = new RealFileSystem[Id] - implicit val printer: ConsoleRealPrinter[Id] = new ConsoleRealPrinter[Id] - val program = new Program[Id, Path, Path] - - program.run(root, "test_dir", List("foo", "bar", "baz")) - - var dir: Path = root.resolve("test_dir") - - Files.exists(dir) shouldBe true - - var fDir: Path = dir.resolve("f") - var bDir: Path = dir.resolve("b") - - Files.exists(fDir) shouldBe true - Files.isDirectory(fDir) shouldBe true - Files.exists(bDir) shouldBe true - Files.isDirectory(bDir) shouldBe true - - val foo: Path = fDir.resolve("foo") - val bar: Path = bDir.resolve("bar") - val baz: Path = bDir.resolve("baz") - - Files.exists(foo) shouldBe true - Files.isRegularFile(foo) shouldBe true - Files.exists(bar) shouldBe true - Files.isRegularFile(bar) shouldBe true - Files.exists(baz) shouldBe true - Files.isRegularFile(baz) shouldBe true - - Files.walk(root).sorted(Comparator.reverseOrder()) - .forEach(file => Files.deleteIfExists(file)) -} \ No newline at end of file