Scala “的通用容器类型(更高种类);“地图”;在斯卡拉

Scala “的通用容器类型(更高种类);“地图”;在斯卡拉,scala,generics,higher-kinded-types,Scala,Generics,Higher Kinded Types,我试图定义一个用容器类型(更高种类)参数化的case类。此容器类型可以是任何类型,只要定义了映射方法即可 我希望通过以下代码实现此结果: import scala.language.higherKinds case class Test[A, C[A]](init: A, trans: Map[A,C[A]]) { def convert[B](conv: A => B): Test[B, C[B]] = { val _init = conv(init) val _t

我试图定义一个用容器类型(更高种类)参数化的case类。此容器类型可以是任何类型,只要定义了映射方法即可

我希望通过以下代码实现此结果:

import scala.language.higherKinds

case class Test[A, C[A]](init: A, trans: Map[A,C[A]]) {
  def convert[B](conv: A => B): Test[B, C[B]] = {
    val _init = conv(init)
    val _trans = trans map {case (k,v) => (conv(k) -> (v map {x => conv(x)})}
    Test(_init, _trans)
  }
}
问题在于代码的
v映射{x=>conv(x)}
部分。由于没有为
C[A]
定义任何绑定,因此显然它不会编译

问题是,此容器类型可以是
Id
(Scalaz样式,但使用
map
而不是
|>
),也可以是
选项
,或者是集合(
Seq
Set
List
,等等)


有没有办法告诉scala编译器容器类型必须有
map
方法?

实现所需的最佳方法是使用type类。 例如,这里有一个使用的示例。
(你也可以用同样的方法)

然而,如果出于某种原因您不能或不想使用Cats/Scalaz,您可以尝试

导入scala.language.higherKinds
导入scala.language.ReflectVeCalls
最终案例类测试[A,C[A]B:C[B]}(init:A,trans:Map[A,C[A]]){
def转换[B](转换:A=>B):测试[B,C]={
val_init=conv(init)
val_trans=trans-map{case(k,v)=>conv(k)->v.map(x=>conv(x))}
测试(_init,_trans)
}
}

尽管如此,请注意最后一个方法将适用于
选项,但对于
列表
将失败,这很简单,因为列表中的
映射
方法接收一个隐式的
CanBuildFrom
,因此它不等于您想要的方法。

实现您想要的最好方法是使用类型类。 例如,这里有一个使用的示例。
(你也可以用同样的方法)

然而,如果出于某种原因您不能或不想使用Cats/Scalaz,您可以尝试

导入scala.language.higherKinds
导入scala.language.ReflectVeCalls
最终案例类测试[A,C[A]B:C[B]}(init:A,trans:Map[A,C[A]]){
def转换[B](转换:A=>B):测试[B,C]={
val_init=conv(init)
val_trans=trans-map{case(k,v)=>conv(k)->v.map(x=>conv(x))}
测试(_init,_trans)
}
}

尽管如此,请注意最后一个方法将适用于
选项
,但对于
列表
,它将失败,原因很简单,因为列表中的
映射
方法接收到一个隐式的
CanBuildFrom
,因此它不等于您想要的方法。

functor类型类如何?functor类型类如何?谢谢,路易斯·米格尔。但是,如果你能再帮我一点的话。我没有养猫的经验。当我尝试应用您的示例并实例化测试类时,我收到以下错误消息:
无法找到参数CFunctor:cats.Functor[Set]
的隐式值。我猜我必须提供隐式参数,但是我该怎么做呢?嗨@Jeff,简单的方法是只导入
cats.implicits.\u
,这将几乎所有库都包含在范围内。或者,如果您只需要set的Functor,您可以从
cats.instances.set.\u
获取它,它将为
set
带来所有隐式实例,包括Functor[set]。要了解更详细的解释,请阅读。谢谢你,路易斯·米格尔。但是,如果你能再帮我一点的话。我没有养猫的经验。当我尝试应用您的示例并实例化测试类时,我收到以下错误消息:
无法找到参数CFunctor:cats.Functor[Set]
的隐式值。我猜我必须提供隐式参数,但是我该怎么做呢?嗨@Jeff,简单的方法是只导入
cats.implicits.\u
,这将几乎所有库都包含在范围内。或者,如果您只需要set的Functor,您可以从
cats.instances.set.\u
获取它,它将为
set
带来所有隐式实例,包括Functor[set]。有关更详细的说明,请阅读。
import scala.language.higherKinds

import cats.Functor
import cats.syntax.functor.toFunctorOps

final case class Test[A, C[_]](init: A, trans: Map[A,C[A]])(implicit CFunctor: Functor[C]) {
  def convert[B](conv: A => B): Test[B, C] = {
    val _init = conv(init)
    val _trans = trans map { case (k,v) => conv(k) -> v.map(x => conv(x)) }
    Test(_init, _trans)
  }
}
import scala.language.higherKinds
import scala.language.reflectiveCalls

final case class Test[A, C[A] <: { def map[B](f: A => B): C[B]}](init: A, trans: Map[A,C[A]]){
  def convert[B](conv: A => B): Test[B, C] = {
    val _init = conv(init)
    val _trans = trans map { case (k,v) => conv(k) -> v.map(x => conv(x)) }
    Test(_init, _trans)
  }
}