Suppose I've got the following algebra for working with file system:
sealed trait Fs[A]
case class Ls(path: String) extends Fs[Seq[String]]
case class Cp(from: String, to: String) extends Fs[Unit]
def ls(path: String) = Free.liftF(Ls(path))
def cp(from: String, to: String) = Free.liftF(Cp(from, to))
And the following interpreter for the algebra:
def fsInterpreter = new (Fs ~> IO) {
def apply[A](fa: Fs[A]) = fa match {
case Ls(path) => IO(Seq(path))
case Cp(from, to) => IO(())
}
}
Now suppose I want to build another algebra that uses the first one. E.g.:
sealed trait PathOps[A]
case class SourcePath(template: String) extends PathOps[String]
def sourcePath(template: String) = Free.liftF(SourcePath(template))
The next thing I want to write an interpreter for PathOps ~> IO which would do something like this:
for {
paths <- ls(template)
} yield paths.head
In other words my interpreter for PathOps should call into Fs algebra.
How do I do that?
FunctionK-~>-nat trafosPathOps ~> Free[Fs, ?]andFs ~> IO? That is: does your desired natural trafoPathOps ~> IOsomehow factor through theFree[Fs, ?]-monad? - Andrey Tyukin