I am trying to find information if it is possible to create a Functor for a Map type.
The docs have information for the List, Option, but not for my case.
Can you please tell me if it is possible to create a Functor[Map[Int, T]]?
Below I will attach an implementation of a similar functor for a List.
trait Functor[F[_]]:
def map[A, B](list: F[A])(f: A => B): F[B]
given Functor[List] with
def map[A, B](list: List[A])(f: A => B): List[B] = ???
Expanding Luis' and Andrey's answers, with Scala 2 and scala-cats try using type alias
import cats.Functor
type MapInt[T] = Map[Int, T]
Functor[MapInt].map(Map(1 -> "woo"))(a => a + "hoo")
// : MapInt[String] = Map(1 -> "woohoo")
or using Scala 2 type lambda "atrocity"
Functor[({type MapInt[T]=Map[Int, T]})#MapInt].map(Map(1 -> "woo"))(a => a + "hoo")
// : MapInt[String] = Map(1 -> "woohoo")
or using kind-projector
Functor[Map[Int, *]].map(Map(1 -> "woo"))(a => a + "hoo")
// : MapInt[String] = Map(1 -> "woohoo")
scastie
Regarding Map being of wrong "kind" for Functor try using the REPL to explore the idea (if you start with sbt console it should load it with all the dependencies from build.sbt):
scala> import cats.Functor
import cats.Functor
scala> :kind -v Functor
cats.Functor's kind is X[F[A]]
(* -> *) -> *
This is a type constructor that takes type constructor(s): a higher-kinded type.
scala> :kind -v Map
Map's kind is F[A1,+A2]
* -> * -(+)-> *
This is a type constructor: a 1st-order-kinded type.
scala> type MapInt[T] = Map[Int, T]
type MapInt
scala> :kind -v MapInt
MapInt's kind is F[A]
* -> *
This is a type constructor: a 1st-order-kinded type.
Note how Functor has higher-order kind
(* -> *) -> *
\______/
|
required shape of type argument to Functor
which means it expects a type constructor of first-order kind, and in particular a type constructor which takes a single type argument
* -> *
|
only one type argument expected
Now Map type constructor by itself does have first-order kind expected by Functor, however it is of wrong arity as it takes two type arguments instead of one
1st arg to Map
|
* -> * --> *
|
2nd arg to Map
hence we need a type lambda to fix the first type parameter of Map to Int whilst keeping second type parameter free which turns it into a type constructor of the correct kind and arity for Functor
scala> :kind -v MapInt
MapInt's kind is F[A]
* -> *
Here is an example of a higher-order type constructor which takes another binary-arity first-order type constructor as its type argument
trait Foo[F[A, B]]
Let's check if Map now fits without having to use a type lambda
scala> trait Foo[F[A, B]]
trait Foo
scala> :kind -v Foo
Foo's kind is X[F[A1,A2]]
(* -> * -> *) -> *
This is a type constructor that takes type constructor(s): a higher-kinded type.
scala> new Foo[Map] {}
val res2: Foo[Map] = $anon$1@589af27e
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With