Scala 简化类型注释

Scala 简化类型注释,scala,types,Scala,Types,我创建了一个pimp方法,collate,可以从任何可遍历的或任何可以强制为可遍历的类型使用,如下例所示: val ints = List(0,9,4,5,-3,-5,6,5,-2,1,0,6,-3,-2) val results = ints collate { case i: Int if(i < 0) => i.floatValue } andThen { case i: Int if(i>5) => i.toString } andThen { cas

我创建了一个pimp方法,
collate
,可以从任何
可遍历的
或任何可以强制为可遍历的类型使用,如下例所示:

val ints = List(0,9,4,5,-3,-5,6,5,-2,1,0,6,-3,-2)
val results = ints collate {
  case i: Int if(i < 0) => i.floatValue
} andThen {
  case i: Int if(i>5) => i.toString
} andThen {
  case i: Int if(i==0) => i
} toTuple

/*
results: (List[Float], List[java.lang.String], List[Int], List[Int]) =
(List(-3.0, -5.0, -2.0, -3.0, -2.0),List(9, 6, 6),List(0, 0),List(4, 5, 5, 1))
*/
从概念上讲,一旦您了解了
如何从
构建,就不那么令人望而生畏了,但我发现它被样板文件淹没了,尤其是隐式的

我知道,通过使用HList,我可以大大简化ResultX逻辑,我可能会这样做,所以这段代码不会让我特别担心

我还知道,如果我能够将
Repr
约束为
Traversable
的一个子类型,我的生活会变得更加轻松。但我拒绝这样做,因为那样它就不能用于字符串了。出于同样的原因,我也希望避免强制分部函数返回T的子类型——尽管这不太重要,因为我总是可以将逻辑分解为不同的collate和map操作

更令人担忧的是,
CanBuildFrom[Repr,T,Repr]
,我似乎一直在重复,这掩盖了我方法签名中的重要内容。这是我确信可以在类级别定义一次的东西,但是我还没有找到一种方法使它工作

有什么想法吗?

只需定义类型:

class Collatable[Repr <% Traversable[T], T](xs: Repr) {

  // Results handling stuff, bit like a poor-man's HList, feel free to skip...

  type With[-Elem] = CanBuildFrom[Repr, Elem, Repr]
  type CanBuild[-Elem, +To] = CanBuildFrom[Repr, Elem, To]

  trait Results {
    def remainder: Repr

    type Append[That] <: Results
    def append[That](tup: (That, Repr)): Append[That]

    def andThen[R, That](pf: PartialFunction[T, R])
    (implicit
      matchesBuilder: CanBuild[R, That],
      remainderBuilder: With[T]
    ) = {
      val more = (new Collatable[Repr,T](remainder)).collateOne[R,That](pf)
      append(more)
    }
  }

  def collateOne[R, That](pf: PartialFunction[T, R])
  (implicit
    matchesBuilder: CanBuild[R, That],
    remainderBuilder: With[T]
  ) = { 
    val matches = matchesBuilder(xs)
    val remainder = remainderBuilder(xs)
    for (x <- xs) if (pf.isDefinedAt(x)) matches += pf(x) else remainder += x
    (matches.result, remainder.result)
  }   
}

类可折叠[Repr我会重命名
,然后将
改为
。顺便说一句,我喜欢这个方法。@Daniel-我会考虑一下这个名字,尽管我不相信
给了把操作链接在一起的正确感觉。我的首选是
然后
,它已经作为一个关键字了,我仍然不知道ded about
+
@Daniel-很高兴你喜欢它,你不想知道我在升级这个东西以处理字符串和可遍历数据时经历了多少变化…我尝试将构建器推到类级别,并将视图绑定到专用隐式中,如你的第二个示例所示。奇怪的是,它没有解决这个问题当我这样做的时候,我再次注意到您在
ev
之前指定了
remainderBuilder
——这与我的测试顺序相反。它真的那么简单吗?当然,可能只是我在编译器中发现了一个bug,它停止了它应有的工作!这肯定已经足够接近流血了类型系统的边缘使之成为可能…类型别名起作用,当然会稍微清理代码,但参数顺序没有什么区别。如果我将该生成器拉到类范围,则该对象将编译,但尝试使用它时隐式解析失败。通过隐式使用
定义生成器[]
类内也有同样的问题。我仍然很困惑,现在我要看看编译而不是使用REPL是否有什么不同。@Kevin如果在类开始时执行
implicit val rB=remainderBuilder
会怎么样?我看不出有什么帮助,隐式解析在类创建时失败。但我愿意尝试这个阶段有什么事吗
class Collatable[Repr <% Traversable[T], T](xs: Repr) {

  // Results handling stuff, bit like a poor-man's HList, feel free to skip...

  type With[-Elem] = CanBuildFrom[Repr, Elem, Repr]
  type CanBuild[-Elem, +To] = CanBuildFrom[Repr, Elem, To]

  trait Results {
    def remainder: Repr

    type Append[That] <: Results
    def append[That](tup: (That, Repr)): Append[That]

    def andThen[R, That](pf: PartialFunction[T, R])
    (implicit
      matchesBuilder: CanBuild[R, That],
      remainderBuilder: With[T]
    ) = {
      val more = (new Collatable[Repr,T](remainder)).collateOne[R,That](pf)
      append(more)
    }
  }

  def collateOne[R, That](pf: PartialFunction[T, R])
  (implicit
    matchesBuilder: CanBuild[R, That],
    remainderBuilder: With[T]
  ) = { 
    val matches = matchesBuilder(xs)
    val remainder = remainderBuilder(xs)
    for (x <- xs) if (pf.isDefinedAt(x)) matches += pf(x) else remainder += x
    (matches.result, remainder.result)
  }   
}