Skip to content

Instantly share code, notes, and snippets.

@afsalthaj
Last active July 29, 2018 05:12
Show Gist options
  • Save afsalthaj/110e01322cc05ef6c7a1e6fa45e95dea to your computer and use it in GitHub Desktop.
Save afsalthaj/110e01322cc05ef6c7a1e6fa45e95dea to your computer and use it in GitHub Desktop.
package io.atlassian.aws
import java.io.File
import scalaz.{Free, Functor}
sealed trait FileActionOp[A]
case class Pure[A](x: A) extends FileActionOp[A]
case class MakeDir[A](d: File, x: A) extends FileActionOp[A]
case class CreateFile[A](d: File, x: A) extends FileActionOp[A]
object X {
implicit val functorF: Functor[FileActionOp] = new Functor[FileActionOp] {
override def map[A, B](fa: FileActionOp[A])(f: A => B): FileActionOp[B] =
fa match {
case Pure(x) => Pure(f(x))
case MakeDir(d, x) => MakeDir(d, f(x))
case CreateFile(d, x) => CreateFile(d, f(x))
}
}
type FileAction[A] = Free[FileActionOp,A]
val createFile: Free[FileActionOp, String] = Free.liftF(CreateFile(new File(""), "afsal"))
val makeDir: Free[FileActionOp, String] = Free.liftF(MakeDir(new File(""), "afsal"))
// My program is doing a lot of input and output operations. First it creates a file. Then it creates a directory.
// Please test if myProgram does the right thing! That it first createFile and then makeDir
val myProgram: Free[FileActionOp, Unit] =
for {
_ <- createFile
_ <- makeDir
} yield ()
// Unwrapping the Free to a list of operations recursively. Yes it is a boiler plate.
// Come on, do you want to write to a file and test?
// Or do you want to make a file operation program and test ? In which case you can test only the final result which is Unit
// Or do you want to write this boiler plate and test if the program has all the steps that are required?
def inspectProgram[A](f: Free[FileActionOp,A]): List[FileActionOp[None.type]] = f.fold(
(a:A) => List(),
(x:FileActionOp[FileAction[A]]) => x match {
case Pure(x) => inspectProgram(x)
case MakeDir(d,x) => MakeDir(d,None) :: inspectProgram(x)
case CreateFile(d,x) => CreateFile(d,None) :: inspectProgram(x)
}
)
}
object Main {
def main(args: Array[String]): Unit = {
val s = X.inspectProgram[Unit](X.myProgram)
// M also worried about the order, and it tests that as well!
assert(s == List(CreateFile(new File(""), None), MakeDir(new File(""), None)))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment