如何解决scala.collection.Map[Int, T] 的函子
如果可以为 Functor
类型创建 Map
,我正在尝试查找信息。
文档包含 List
、Option
的信息,但没有针对我的情况。
你能告诉我是否可以创建一个 Functor[Map[Int,T]]
吗?
下面我将附上一个 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] = ???
解决方法
扩展 Luis 和 Andrey 的答案,使用 Scala 2 和 scala-cats 尝试使用类型别名
import cats.Functor
type MapInt[T] = Map[Int,T]
Functor[MapInt].map(Map(1 -> "woo"))(a => a + "hoo")
// : MapInt[String] = Map(1 -> "woohoo")
或使用 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")
或使用 kind-projector
Functor[Map[Int,*]].map(Map(1 -> "woo"))(a => a + "hoo")
// : MapInt[String] = Map(1 -> "woohoo")
关于 Map
对 Functor
是错误的“种类”尝试使用 REPL 来探索这个想法(如果你从 sbt console
开始,它应该加载它与 {{ 1}}):
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.
如何具有高阶种类
Functor
这意味着它需要一个一阶类型的类型构造函数,特别是一个接受单个类型参数的类型构造函数
(* -> *) -> *
\______/
|
required shape of type argument to Functor
现在 * -> *
|
only one type argument expected
类型构造函数本身确实具有 Map
期望的一阶类型,但是它是错误的arity,因为它需要两个类型参数而不是一个
Functor
因此我们需要一个类型 lambda 来将 1st arg to Map
|
* -> * --> *
|
2nd arg to Map
的第一个类型参数固定为 Map
,同时保持第二个类型参数自由,从而将其转换为 {{1 的正确种类和数量的类型构造函数}}
Int
这是一个高阶类型构造函数的例子,它采用另一个二元一阶类型构造函数作为其类型参数
Functor
让我们检查 scala> :kind -v MapInt
MapInt's kind is F[A]
* -> *
现在是否适合而无需使用类型 lambda
trait Foo[F[A,B]]
,
-
Map[A,B]
与A => B
几乎相同,但具有有限域。 -
A => B
基本上是Reader[A,B]
-
Reader[A,B]
是一个 monad - 所有的 monad 都是函子
所以,是的,让我们尝试做与 Reader
相同的事情:它只是对赋予 map
的函数进行后期组合:
given mapFunctor[K]: Functor[[V] =>> Map[K,V]] with
def map[A,B](m: Map[K,A])(f: A => B): Map[K,B] = m.view.mapValues(f).toMap
toMap
是必需的,因为 mapValues
是非严格的(它拒绝立即映射所有值,并将函数组合保持在符号 MapView
中)。>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。