Generics Scala解构然后重建一个Iterable

Generics Scala解构然后重建一个Iterable,generics,scala,trie,Generics,Scala,Trie,我目前正致力于在Scala中实现我自己的功能(出于学习/爱好的目的),并且我正试图保持它的通用性(以便它可以存储任何Iterable,而不仅仅是字符串)。我的班级签名看起来像 class Trie[Item <% Iterable[Part], Part](items: Item*) extends Set[Item] class-Trie[项目'l'->'e'->'h') 现在我的问题是,因为我试图保持事物的通用性,所以我没有办法从它的“部分”重构“项目”因此,我向So的人们提出的问题

我目前正致力于在Scala中实现我自己的功能(出于学习/爱好的目的),并且我正试图保持它的通用性(以便它可以存储任何Iterable,而不仅仅是字符串)。我的班级签名看起来像

class Trie[Item <% Iterable[Part], Part](items: Item*) extends Set[Item]
class-Trie[项目'l'->'e'->'h')


现在我的问题是,因为我试图保持事物的通用性,所以我没有办法从它的“部分”重构“项目”因此,我向So的人们提出的问题是,处理这个问题的最优雅的方式是什么?我是否应该在构造函数参数中添加一个重构函数?是否应该对
Item
使用不同的边界来强制函数的存在?还是完全是另一种方式?

Item和Part之间存在一种隐含的关系他说,您需要将项目分解为零件对象,而要重建项目,则需要执行相反的操作

因此,使用
“hello”:String
,您需要
f(“hello”)
返回
('h':Char,“ello”:String)
,并且需要反向函数
g('h',“ello”)
返回
“hello”

因此,只要遵循一些规则,任何两种类型和两个这样的函数都可以。我认为这些规则很容易理解。这或多或少是您如何使用
head
tail
递归分解列表,并使用

您可以使用上下文绑定为常规类型提供这些函数

(编辑)

实际上,我不能真正使用上下文绑定,因为有两个类型参数,但这就是我的想法:

trait R[Item, Part] {
  def decompose(item: Item): (Part, Item)
  def recompose(item: Item, part: Part): Item
  def empty: Item
}

class NotATrie[Item, Part](item: Item)(implicit rel: R[Item, Part]) {
  val brokenUp = {
    def f(i: Item, acc: List[Part] = Nil): List[Part] = {
      if (i == rel.empty) acc
      else {
        val (head, tail) = rel.decompose(i)
        f(tail, head :: acc)
      }
    }
    f(item)
  }

  def rebuilt =  (rel.empty /: brokenUp)( (acc, el) => rel.recompose(acc, el) )
}
然后我们提供一些隐式对象:

隐式对象string2R扩展R[String,Char]{
def decompose(item:String):(Char,String)=(item.head,item.tail)
def重新组合(项目:字符串,部分:字符):字符串=部分+项目
def empty:String=“”
}
隐式对象String2Alt扩展了R[String,Int]{
def分解(项目:字符串):(整数,字符串)={
val cp=项。代码点位于(0)
val索引=字符数。字符数(cp)
(cp,项目子字符串(索引))
}
def重新组合(项目:字符串,部分:Int):字符串=
新字符串(Character.toChars(part))+项
def empty:String=“”
}
val nat1=new NotATrie[String,Char](“你好”)
nat1.brokenUp//List(o,l,l,e,h)
你好
val nat2=new NotATrie[String,Int](“hello\ud834\udd1e”)
nat2.brokenUp//List(11907011108108101104)

nat2.0//helloSo边界看起来像是带有{def cons(p:Part,i:Item)=>Item}的
Item(Part,Item)}
。我知道这在语法上可能是错误的,但这是正确的想法吗?我已经根据您指出的内容进行了更改,但是带有隐式对象的部分似乎只能通过命令行/脚本界面工作。如果我尝试在顶级定义隐式生成器对象,编译器会抱怨,但如果我将其包装在顶级obj中ect则无法找到隐式转换。如果我想向用户提供隐式构建器而无需任何额外的麻烦,我应该在哪里定义它们?将隐式对象放在
对象R{…}
中,编译器应该在伴随对象中搜索隐式定义。