augustjune/canoe

Functor syntax and so on

Closed this issue · 2 comments

It would be nice to use the syntax given by cats.implicits._ when working with Scenario[F, A].

I see that it's defined as:

type Scenario[F[_], A] = Episode[F, TelegramMessage, A]

And that Episode defines a Monad instance but it might need something else to pick up the syntax. For example:

def repeat[F[_]: TelegramClient: Timer](chat: Chat, i: Int): Scenario[F, Unit] =
  if (i <= 0) Scenario.eval(chat.send("Done.")).map(_ => ())
  else
    for {
      _ <- Scenario.eval(chat.send(s"$i.."))
      _ <- Scenario.eval(Timer[F].sleep(1.second))
      _ <- repeat(chat, i - 1)
    } yield ()

I would like to be able to do:

Scenario.eval(chat.send("Done.")).void

But that's just an example.

As you noticed Episode forms a monad, but it requires Applicative instance for the effect type:

implicit def monadInstance[F[_]: Applicative, I]: Monad[Episode[F, I, *]] = ???

So if you add Applicative to the F context bound you can actually use cats syntax:

def repeat[F[_]: TelegramClient: Applicative: Timer](chat: Chat, i: Int): Scenario[F, Unit] =
  if (i <= 0) Scenario.eval(chat.send("Done.")).void
  else ???

It shouldn't be the case that you don't have Applicative for your F, since TelegramClient requires ConcurrentEffect, but I also don't like this restriction.

I think I will be able to get rid of this requirement after #31 is done.

Oh I completely missed that! 😄 It makes sense then, thanks!