Как настроить таймер кошек на абстрактный эффект

Скажем, у меня есть следующая подпись метода в проекте, использующем Cats-effect и окончательный подход без тегов:

def schedule[F[_]: Applicative : Async: Timer]

Я пытаюсь запланировать операцию на schedule вызов метода с использованием чистого FP.

Я пробовал так:

Timer[F].sleep(FiniteDuration(10, TimeUnit.SECONDS)) *> {
    Applicative[F].pure(println("tick"))
}

но это не сработало, потому что эффект println("tick") казнен на Timer этап инициализации.

Как я могу заставить его работать правильно?

Могу ли я также создать какую-то рекурсивную конструкцию, чтобы повторять запланированную операцию каждые 10 секунд?

2 ответа

Решение

Applicative[F].pureне задерживает эффект. Он только увеличивает чистую ценностьF. Поскольку у вас естьAsync привязанный к контексту, я бы предложил Async[F].delay(println("tick")).

Вы можете легко вызвать это рекурсивно так:

def schedule[F[_]: Async: Timer]: F[Unit]

def repeat[F[_]: Async: Timer]: F[Unit] =
  schedule >> repeat

Просто используя приведенное выше, чтобы написать полный пример. Кредит им.

      package com.example.timerapp

import cats.Applicative
import cats.effect.{Async, ExitCode, IO, IOApp, Timer}
import cats.syntax.apply._
import cats.syntax.flatMap._
import scala.concurrent.duration._
import java.time.Instant

object TimerApp extends IOApp {

  override def run(args: List[String]): IO[ExitCode] = {
    repeat[IO].as(ExitCode.Success)
  }

  def schedule[F[_]: Applicative: Async: Timer]: F[Unit] =
    Timer[F].sleep(1 second) *> {
      Async[F].delay(println(Instant.now.toString))
    }

  def repeat[F[_]: Async: Timer]: F[Unit] =
    schedule[F] >> repeat

}

Другие вопросы по тегам