繁体   English   中英

在为工厂生成“ X”类型的容器进行编码时,如何通用地处理Scala类型更高的类型

[英]how to generically handle Scala Higher-kinded types when coding factories for generating containers of items of type 'X'

在学习了本教程中的Scala高级类型的一些示例之后,我开始怀疑是否可以编写一个方法来处理定义为高级类型的特征的两个子类。

本教程定义了此特征(稍微复杂一些):

trait ContainerFactory[M[_]] { def put[A](x: A): M[A] }

我将其理解为类型参数化工厂的签名,该工厂创建不同类型的容器( ListsSet s等,其中容器的类型由M给出)以及通过放置插入到容器中的对象的类型方法由A给出。 在实例化容器的调用站点(我认为这是正确的术语)上,指定所需的容器类型(如注释行中所示: //factory for List containers)

val factory = new ContainerFactory[List] { def put[A](x: A) = List(x)  } // factory for List containers
factory.put("dog") // insert an element of type String to factory
res5: List[String] = List(dog)          //  and you get a List of String

factory.put(1)// insert an element of type Int to factory
res6: List[Int] = List(1) // and you get a List of Int

val factory2 = new ContainerFactory[Set] { def put[A](x: A) = Set(x)} // factory for Set containers
factory2.put("dog")
factory2.put(1)

我的目标是创建一个将ContainerFactory和对象放入生成的容器的方法。 我希望该方法生成参数化的合适容器( ListSet ),以容纳我作为第二个对象传入的对象的类型。

我认为像下面这样的方法确实很酷而且有用,但是我在使用Scala语法方面遇到麻烦,无法使其正常工作。 实际上,我什至不知道是否可能。

// Code below does not compile
// Method for generating container (of type defined by first arg) that contains the second argument, and 
// which (after instantiation) is parameterized to hold  only objects of that type:

def genContainer[M[T]](factory: ContainerFactory[M], item : T) = {
    factory.put(item)
}


genContainer(factory2, "x")
// desired return value =>    Set[String] = Set(x)

genContainer(factory, 11)
// desired return value =>    List[Int] = List(11)

注意:尝试定义genContainer时出现的错误是:

<console>:10: error: not found: type T
       def genContainer[M[T]]( factory :  Container[M]  ,  item : T) = {

注意2:我可以定义这样的方法,该方法采用通用的ContainerFactory

def genContainer[M[T]](factory:  ContainerFactory[M]) = { }

但是,当我尝试将第二个参数指定为类型T (在参数化中引用)时,出现未找到的有关T的错误。

你很亲密 问题是您需要分别声明类型参数:

def genContainer[T, M[_]](factory: ContainerFactory[M], item: T) =
  factory.put(item)

这有点令人困惑,因为以下代码可以编译:

def genContainer[M[T]](factory: ContainerFactory[M]) = "whatever"

不过,这里T的范围仅限于M[...]内部(有关详细信息,请参见语言规范的 4.4节)。 当您声明像M[T <: Foo[T]]这样的花哨边界时,这可能很方便,但是通常给类型构造函数的type参数起个名字只是噪音,最好与M[_]一起使用(与M[A]完全等效)。

你真的很亲密:

def genContainer[T, M[_]](factory:  ContainerFactory[M], item: T) = {
    factory.put(item)
}

您所要做的就是将每个类型参数指定为顶级类型参数! 而且编译器很聪明,可以在许多情况下推断出这些类型参数:

val factory = new ContainerFactory[List] { def put[A](x: A) = List(x)  }
genContainer(factory, "foo") //No need to specify the type parameters!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM