Search code examples
scalatypeclassscala-catssubtyping

Cats instances for Some and None et al


In Scala 2.13 and Cats, the following works fine:

import cats.implicits._
Traverse[Option]

However the following fails:

import cats.implicits._
Traverse[Some]

I would like for the latter to work, not only for Traverse of Option subclasses, but for any type that has a parent that there exists a given typeclass for.

I have tried creating a method with implicit proof <:< but can't quite get it to work.


Solution

  • If you really understand what you do you can define necessary instance manually (when it exists).

    Some is isomorphic to Id.

    implicit val someTraverse: Traverse[Some] = new Traverse[Some] {
      override def traverse[G[_]: Applicative, A, B](fa: Some[A])(f: A => G[B]): G[Some[B]] = f(fa.value).map(Some(_))
      override def foldLeft[A, B](fa: Some[A], b: B)(f: (B, A) => B): B = f(b, fa.value)
      override def foldRight[A, B](fa: Some[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = f(fa.value, lb)
    }
    

    Generally this is not possible. If F is a functor and G[T] <: F[T] for all T then G is not necessarily a functor.

    Calling generic function with Functor using subclass (cats/scalaz)

    Also sometimes you can derive type classes using kittens.

    Why can find `Functor` instance for Tree but not for Branch or Leaf?