gpt4 book ai didi

scala - 简化类型注解

转载 作者:行者123 更新时间:2023-12-04 21:50:54 24 4
gpt4 key购买 nike

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

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))
*/

把它想象成一个联合'twixt collect 的邪恶产物和 partition ,如果你愿意...

它是这样定义的:
import collection.generic.CanBuildFrom

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

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

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: CanBuildFrom[Repr, R, That],
remainderBuilder: CanBuildFrom[Repr, T, Repr]
) = {
val more = (new Collatable[Repr,T](remainder)).collateOne[R,That](pf)
append(more)
}
}

case class Results9[M1,M2,M3,M4,M5,M6,M7,M8,M9](
m1: M1, m2: M2, m3: M3, m4: M4, m5: M5, m6: M6, m7: M7, m8: M8, m9: M9,
remainder: Repr)
extends Results {
implicit def toTuple = (m1, m2, m3, m4, m5, m6, m7, m8, m9, remainder)
def append[That](tup: (That, Repr)) = error("too many")
}

// ... skip a bit, still in results logic ...

case class Results2[M1,M2](
m1: M1, m2: M2, remainder: Repr)
extends Results {
implicit def toTuple = (m1, m2, remainder)
type Append[That] = Results3[M1,M2,That]
def append[That](tup: (That, Repr)) = Results3(m1, m2, tup._1, tup._2)
}

case class Results1[M1](matches: M1, remainder: Repr) extends Results {
implicit def toTuple = (matches, remainder)

type Append[That] = Results2[M1, That]
def append[That](tup: (That, Repr)) = Results2(matches, tup._1, tup._2)
}

// and now... Our feature presentation!

def collateOne[R, That](pf: PartialFunction[T, R])
(implicit
matchesBuilder: CanBuildFrom[Repr, R, That],
remainderBuilder: CanBuildFrom[Repr, T, Repr]
) = {
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)
}

def collate[R, That](pf: PartialFunction[T, R])
(implicit
matchesBuilder: CanBuildFrom[Repr, R, That],
remainderBuilder: CanBuildFrom[Repr, T, Repr]
): Results1[That] = {
val tup = collateOne[R,That](pf)
Results1(tup._1, tup._2)
}
}

object Collatable {
def apply[Repr, T](xs: Repr)(implicit witness: Repr => Traversable[T]) = {
new Collatable[Repr, T](xs)
}
}

implicit def traversableIsCollatable[CC[X] <: Traversable[X], A](xs: CC[A]) =
Collatable[CC[A], A](xs)
implicit def stringIsCollatable(xs: String) =
Collatable[String, Char](xs)

从概念上讲,一旦您了解了 CanBuildFrom工作,但我发现它被样板淹没了 - 特别是隐含的。

我知道我可以通过使用 HList 来大大简化 ResultX 逻辑,这也是我可能会做的事情,所以那段代码不会让我特别担心。

我也知道,如果我能够约束 Repr,我可以让我的生活变得更加轻松。作为 Traversable 的子类型.但我拒绝这样做,因为那样就不能用于字符串。出于同样的原因,我也想避免强制部分函数返回 T 的子类型 - 尽管这不是什么问题,因为我总是可以将我的逻辑分解为不同的整理和映射操作。

更多关注的是 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)
}
}

另一方面,我刚刚注意到整个 CollatableRepr 上参数化和 T ,那么你为什么不得到隐含的 remainderBuilder在那个级别? 编辑 因为 T还没有推断出来。现在,我不知道如何摆脱额外的隐含。

关于scala - 简化类型注解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4814495/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com