Cannot find Bind instances for Free Monads over Coyoneda when composing functions via Kleisli arrows in scalaz

242 Views Asked by At

Thank you in advance for your help

I have 2 functions that I am trying to compose via Kleisli arrows. The functions accept String and produce FreeC. The kleisli arrows are created without an issue but the compiler is complaining that it cannot find. I will cut out some of the code for simplicity:

import scalaz._
import Scalaz._
import Free.FreeC
import Free._
import Kleisli._

trait AppCompose {

  def lift[F[_], G[_], A](fa: F[A])(implicit I: Inject[F, G]): FreeC[G, A] =
    Free.liftFC(I.inj(fa))

}

object BigBrother {

  sealed trait Sensor[A]
  case class Log(log: String) extends Sensor[Unit]
  case class Filter(log: String) extends Sensor[String]
  case class Secure(log: String) extends Sensor[String]

}

import BigBrother.Sensor

class BigBrother[F[_]](implicit I: Inject[Sensor,F]) extends AppCompose {
  import BigBrother._

  type FreeString[A] = FreeC[F,String]

  def log(log: String) = lift(Log(log))
  def filter(log: String) = lift(Filter(log))
  def secure(log: String) = lift(Secure(log))

  def filterAndSecure(phrase: String) = for {
    f <- filter(phrase)
    s <- secure(f)
  } yield s

  // kleisli composition attempt - alternative to filterAndSecure
  val fk = kleisli[FreeString, String, String](filter _)
  val sk = kleisli[FreeString, String, String](secure _)
  val fAndS = fk >=> sk // this is where we have a compilation issue

}

For some reason what i get is this compilation error:

could not find implicit value for parameter b: scalaz.Bind[FreeString]
[error]   val fAndS = sk >=> fk

feels like the implicit should be resolved since FreeC in a monad instance that implements a Bind trait and i am importing all of the Free implicit instances via import Free._

what am I missing here?

Thank you in advance!

1

There are 1 best solutions below

0
On BEST ANSWER

Thank you Travis for your help. Bad type declaration was actually one of the culprits. With some help from the scalaz community via google groups and some tinkering here is the answer:

class BigBrother[F[_]](implicit I: Inject[Sensor,F]) extends AppCompose {
  import BigBrother._

  def log(log: String) = lift(Log(log))
  def filter(log: String) = lift(Filter(log))
  def secure(log: String) = lift(Secure(log))

  def filterAndSecure(phrase: String) = for {
    f <- filter(phrase)
    s <- secure(f)
  } yield s

  type CoyoF[A] = Coyoneda[F, A]
  type FreeCoF[A] = Free[CoyoF,A]

  implicit val MonadFreeSensor = Free.freeMonad[FreeCoF]

  // kleisli composition attempt - alternative to filterAndSecure
  val fk = kleisli[FreeCoF, String, String](filter _)
  val sk = kleisli[FreeCoF, String, String](secure _)
  val fAndS = fk >=> sk

}

key is the correct type declaration and providing the type class monad instance for FreeCoF implicit val MonadFreeSensor = Free.freeMonad[FreeCoF]