高集类型用于多集 [英] Higher-kinded types for multisets

查看:101
本文介绍了高集类型用于多集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Scala中编写一个Multiset[T, S[_]]类,它带有2个类型参数:T是元素的类型,而S是集合的基础表示. 在此多集中,构造了S[(T, Int)]的实例(在每对中,T是元素,而Int是其出现次数). 这在C ++中是可能的:

I would like to write a Multiset[T, S[_]] class in Scala, which takes 2 type parameters: T is the type of the element, whereas S is the underlying representation of the set. In this multiset, an instance of S[(T, Int)] is constructed (in each pair, T is the element and Int is its number of occurrence). This is possible in C++:

template<typename T, template<typename> S>

两个问题:

  • 如何声明对S的约束它必须是集合? Multiset[T, S[_] <: Set[_]]是否有效?

  • How to declare the constraint on S that it must be a set? Does Multiset[T, S[_] <: Set[_]] work?

是否可以声明可以实例化S[(T, Int)]实例的约束?这可以使用where S: new()约束在C#中完成.

Is it possible to declare the constraint that an instance of S[(T, Int)] can be instantiated? This can be done in C# using the where S: new() constraint.

推荐答案

第一个问题:改用S[X] <: Set[X].使用下划线标记高阶类型的参数很方便,不需要用无用的名称引起注意,但是实际上您可以使用任何标识符.对于这种特殊情况,下划线将不起作用.您甚至可以执行S[X] <: Set[List[X]]之类的操作.

First question: Use S[X] <: Set[X] instead. Using underscore to mark higher order type params is convenient, no need to catch the attention with an useless name, but you can in fact use any identifier. And for this particular case, underscore will not work. You could even do things like S[X] <: Set[List[X]].

第二个问题:没有直接等价的内容,但是我很少在C#中使用它,因为这意味着只能由无参数构造函数创建对象,这是一个很大的限制,对所有可能的用法都有效您的代码.例如,您的类的用户可能希望在初始化时设置容量,或者使用池或其他方法.在大多数情况下,我在构造函数中需要一个Func<S>委托,并且我可能会添加一个静态工厂,该工厂接受new作为

Second question: no direct equivalent, however I rarely use that in C# because it implies that object can only be created by the parameterless constructor, which is a big restriction, in force for all possible usage of your code. The user of your class might like for instance to set the capacity at initialization, or use a pool or whatever. Most of the time, I requires a Func<S> delegate in the constructor, and I may add a static factory which accepts new as a convenience as in

class Generic<T> 
{
   public Generic(..., Func<T> factory)
}

static class Generic 
{
  public Generic<T> Create(....) where T : new {
    return new Generic(..., () => new T());
  }
}

在scala中,您将需要传递函数.一种可能的替代方法是使用隐式参数,例如

In scala, you will need to pass the function. A possible alternative is to use an implicit parameter, e.g.

trait Builder[A] {
   def build(): A
}

object Builder {
  def build[A: Builder] : A = implicitly[Builder[A]].build()
}

class Generic[A: Builder](....) {....
    ...
    // instead of val a = new A()
    val a = Builder.build[A]
    ....
}

然后,您只需确保可以在参数类型的隐式范围内使用构建器,并且默认情况下将使用该构建器.当默认值不是您想要的值时,您仍然可以显式地传递另一个值.

Then you can just ensure that a builder is available in implicit scope for your parameter type, and it will be used by default. And you may still pass another one explicitly when the default one is not what you want.

这篇关于高集类型用于多集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆