0

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.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
eirirlar
  • 814
  • 6
  • 24
  • 1
    **cats** does not have those, and you should never need them. The very fact that `Some` exists as a type is a bad consequence of the _OOP_ parts of the language. Care to explain why would you want those? – Luis Miguel Mejía Suárez Sep 01 '19 at 21:24
  • 1
    @LuisMiguelMejíaSuárez Actually this is not necessarily because of OOP. In Haskell (`data Option a = Some a | None`) `Some` and `None` are not types. But with language extension "data kinds" switched on they are (type-level programming) https://stackoverflow.com/questions/20558648/what-is-the-datakinds-extension-of-haskell – Dmytro Mitin Sep 01 '19 at 21:51
  • @DmytroMitin Interesting, thanks for sharing. – Luis Miguel Mejía Suárez Sep 01 '19 at 21:56

1 Answers1

2

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?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66