I’m unable to define a `Functor`

for my `abstract class Foo[V : Monoid]`

that have a type constraint. this is because of the `map`

method of `Functor`

which takes a `B`

parameters which is not a `Monoid`

.

My question is how and where can I add such constraint ?

Here’s a sample from what I’m trying to do :

```
import cats.Functor
import cats.kernel.Monoid
abstract class Foo[A : Monoid] {
val a: A
}
object Foo {
implicit def FooFunctor = new Functor[Foo] {
override def map[A, B](fa: Foo[A])(f: (A) => B) = new Foo[B] {
override val a: B = f(fa.a)
}
}
}
```

this raise the following exception :

```
Error:(12, 59) could not find implicit value for evidence parameter of type cats.kernel.Monoid[B]
override def map[A, B](fa: Foo[A])(f: (A) => B) = new Foo[B] {
```

My first solution was adding the constraint in the `map`

definition (`override def map[A, B : Monoid]`

) but this is not legal because this will change the definition of the function in `Functor`

and will raise the Exception :

```
Error:(12, 18) method map overrides nothing.
```

Can anyone please help me get out of this ? any suggestion would be appreciated.

You’ve found just the direct problem,

this is not legal because this will change the definition of the function

but the real lesson is stated the other way: you cannot write a suitable `Functor`

for `Foo`

, because `Foo`

doesn’t meet the minimum requirements. Speaking as informally as possible, those are “you can map `A`

to anything you like, because it’s completely irrelevant to the structure of `Foo`

.”

You can look for constrained functors, but IMO this approach doesn’t give us enough in generality to make up for what we lose in reason-ability. And you can tell that the FP community has mostly come to the same conclusion, because this “solution” has been well-known for some time.

So I would suggest not trying to change `Functor`

to fit your code, but maybe your code to fit `Functor`

.

One approach you can take is to use `Coyoneda`

, as described by @puffnfresh in How can we map a Set? on typelevel blog.

But there is probably an even better, direct approach: take the `Monoid`

constraint off the type parameter to `Foo`

and move it to the *operations* that need it. (If `map`

is one of those, then you really don’t have a `Functor`

after all, not in this category anyway.) Consider, for example, a `TreeMap`

: while `Ordering`

of the type parameter is needed to look up keys, it is not required to count or fold over the entries.

```
abstract class Foo[A] {
val a: A // don't need it for this
def map[B](f: A => B): Foo[B] // hope you don't need it for this
// but maybe you need it for this
def append(o: Foo[A])(implicit A: Monoid[A]): Foo[A]
// and so on
}
```

1 Like