It is a scheduler of tasks. You can think of it as the purely functional equivalent of:

It provides:

  • The ability to get the current time.
  • Ability to delay the execution of a task with a specified time duration.

It does all of that in an F[_] monadic context that can suspend side effects and is capable of asynchronous execution (e.g. IO).

This is NOT a typeclass, as it does not have the coherence requirement.

import cats.effect.Clock
import scala.concurrent.duration.{FiniteDuration, TimeUnit}

trait Timer[F[_]] {
  def clock: Clock[F]
  def sleep(duration: FiniteDuration): F[Unit]

As mentioned in the IO documentation, there’s a default instance of Timer[IO] available. However, you might want to implement your own to have a fine-grained control over your thread pools. You can look at the mentioned implementation for more details, but it roughly looks like this:

import java.util.concurrent.ScheduledExecutorService

import cats.effect.{IO, Timer, Clock}
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._

final class MyTimer(ec: ExecutionContext, sc: ScheduledExecutorService) extends Timer[IO] {
  override val clock: Clock[IO] =
    new Clock[IO] {
      override def realTime(unit: TimeUnit): IO[Long] =
        IO(unit.convert(System.currentTimeMillis(), MILLISECONDS))

      override def monotonic(unit: TimeUnit): IO[Long] =
        IO(unit.convert(System.nanoTime(), NANOSECONDS))

  override def sleep(timespan: FiniteDuration): IO[Unit] =
    IO.cancelable { cb =>
      val tick = new Runnable {
        def run() = ec.execute(new Runnable {
          def run() = cb(Right(()))
      val f = sc.schedule(tick, timespan.length, timespan.unit)

Also see these related data types:

  • Clock: for time measurements and getting the current clock
  • ContextShift: the pure equivalent of an ExecutionContext