Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -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
9 changes: 9 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -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"
1 change: 1 addition & 0 deletions project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version = 1.3.10
104 changes: 104 additions & 0 deletions src/main/scala/main.scala
Original file line number Diff line number Diff line change
@@ -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"))
}
}



44 changes: 44 additions & 0 deletions src/test/scala/test.scala
Original file line number Diff line number Diff line change
@@ -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))
}