allidoiswin
allidoiswin

Reputation: 2589

Making my own Functor typeclass in Scala

So I wanted to make my own Functor to play around with typeclassing. However I ran into a bunch of issues. The endgoal is to be able to say something like Seq(1,2,3).fmap(2*_).

I came up with this trait which all my Google searches (kind of) agree on:

trait Functor[F[_]] {
  def fmap[A, B](r: F[A], f: A => B): F[B]
}

I'm assuming there's no easy way to link the A to the F[_], i.e. "F[A]".

But I'm having serious trouble creating an implicit to connect to Seq. Here's one try:

implicit class SeqFunctorOps[A](xs: Seq[A]) {
  def fmap[B](f: A => B) = xs map f
}

But that doesn't fit into my Functor, so let's extend it:

implicit class SeqFunctorOps[A](xs: Seq[A]) extends Functor[Seq] {
  def fmap[A, B](f: A => B) = xs map f
}

But that doesn't work because in fmap[A, B]..., the A is a new generic type, and doesn't tie in with xs: Seq[A].

Is there a way to tie them in?

However, it also seems to me that implicit class is not the way to go, considering that other online resources have pointed to using the companion object, but I just can't seem to make it work.

object Functor {
  implicit def SeqFunctor: Functor[Seq] = new Functor[Seq] {
    def fmap[A, B](r: Seq[A], f: A => B) = r map f
  }
}

implicit class SeqFunctorOps[A](xs: Seq[A])(implicit F: Functor[Seq]) {
  def fmap[B](f: A => B) = F.fmap(xs, f)
}

This kind of seems to work, but looks off.

Is there a general pattern to use when trying to do something like this?

Upvotes: 1

Views: 190

Answers (1)

allidoiswin
allidoiswin

Reputation: 2589

Glory be to @drexin, this seems to be good enough:

trait Functor[F[_]] {
  def fmap[A, B](r: F[A], f: A => B): F[B]
}

object Functor {
  implicit def SeqFunctor: Functor[Seq] = new Functor[Seq] {
    def fmap[A, B](r: Seq[A], f: A => B) = r map f
  }
  implicit class Ops[A, F[_]: Functor](xs: F[A]) {
    def fmap[B](f: A => B) = implicitly[Functor[F]].fmap(xs, f)
  }
}

Upvotes: 1

Related Questions