Scala, код с free monad не компилируется, если в операции есть параметр с типом содержащим F[_]
Разбираюсь с free monad, но не получается понять как правильно написать код, если один из классов принимает например fs2.Stream.
Пример кода:
import cats.effect.{Async, IO, IOApp}
import cats.free.Free
import cats.syntax.all._
import cats.{Monad, ~>}
import dev.free.A._
object Example extends IOApp.Simple {
override def run: IO[Unit] = {
val stream =
fs2.Stream.emit[IO, String]("example").through(fs2.text.utf8.encode)
write("/a/b/c", stream).foldMap(compiler)
}
private def compiler: ActionA ~> IO = new (ActionA ~> IO) {
override def apply[A](fa: ActionA[A]): IO[A] = {
fa match {
case Write(path, data) => data.through(fs2.text.utf8.decode).compile.string.flatMap { s =>
IO.println(s"$path; $s")
}
}
}
}
}
object A {
sealed trait ActionA[A]
case class Write(path: String, data: fs2.Stream[_, Byte]) extends ActionA[Unit]
type Action[A] = Free[ActionA, A]
def write(path: String, data: fs2.Stream[_, Byte]): Action[Unit] = Free.liftF[ActionA, Unit](Write(path, data))
}
Ошибка при компиляции:
Example.scala:35:44
_$2 takes no type parameters, expected: 1
def write(path: String, data: fs2.Stream[_, Byte]): Action[Unit] = Free.liftF[ActionA, Unit](Write(path, data))
Все проблемы из за того что не указан тип эффекта для fs2.Stream в Write и я не понимаю как это сделать.
Ответы (1 шт):
Автор решения: Bleser
→ Ссылка
Вот этот код работает.
import cats.effect.{Async, IO, IOApp}
import cats.free.Free
import cats.syntax.all._
import cats.{Monad, ~>}
import dev.free.A._
object Example extends IOApp.Simple {
override def run: IO[Unit] = {
val stream =
fs2.Stream.emit[IO, String]("example").through(fs2.text.utf8.encode)
write("/a/b/c", stream).foldMap(compiler)
}
private def compiler: ActionA ~> IO = new (ActionA ~> IO) {
override def apply[A](fa: ActionA[A]): IO[A] = {
fa match {
case o: Write[IO] => o.data.through(fs2.text.utf8.decode).compile.string.flatMap { s =>
IO.println(s"${o.path}; $s")
}
}
}
}
}
object A {
sealed trait ActionA[A]
case class Write[F[_]](path: String, data: fs2.Stream[F, Byte]) extends ActionA[Unit]
type Action[A] = Free[ActionA, A]
def write[F[_]](
path: String,
data: fs2.Stream[F, Byte]
): Action[Unit] = Free.liftF[ActionA, Unit](Write[F](path, data))
}