Scala:我应该使用什么模式来创建Int、Double和String的通用抽象?
我需要重构我的整个系统,我想听听关于如何处理类型问题的建议 我有这样的情况:我使用的是PMML(基本上是一种带有数据模式规范的XML)和HBase(一种不保留数据类型模式的柱状存储)。我需要在操作系统中的值时匹配这两个值。因此,我需要有一个抽象来处理所有可能成为系统一部分的数据类型。现在我有Int,Double和String 对于每种类型,我都需要能够定义一个解析器(用于HBase)、一个编写器和一组定义为高阶函数的操作(Scala:我应该使用什么模式来创建Int、Double和String的通用抽象?,scala,design-patterns,Scala,Design Patterns,我需要重构我的整个系统,我想听听关于如何处理类型问题的建议 我有这样的情况:我使用的是PMML(基本上是一种带有数据模式规范的XML)和HBase(一种不保留数据类型模式的柱状存储)。我需要在操作系统中的值时匹配这两个值。因此,我需要有一个抽象来处理所有可能成为系统一部分的数据类型。现在我有Int,Double和String 对于每种类型,我都需要能够定义一个解析器(用于HBase)、一个编写器和一组定义为高阶函数的操作((T,T)=>T) 现在我试着用一个trait MyValue[T]来做这
(T,T)=>T)
现在我试着用一个trait MyValue[T]
来做这件事,它被MyValueInt extends MyValue[Int]
或MyValueDouble extends MyValue[Double]
扩展。我可以定义一个像list[(MyValue,MyValue)=>MyValue]这样的操作列表,但是每次我都必须将它与每个案例匹配,并且在类型系统中产生了许多其他问题
我需要的是一个很好的抽象,以模拟这些值只能是Int、Double和string的事实,创建这些值的列表,并能够使用通用逻辑处理这些值,直到我需要提取实际值并将其应用于操作为止。类型类看起来像是解决问题的方法
// Define the behaviors you want your types to support
trait Parser[T] {
def parse(s: String): T
}
trait Writer[T] {
def write(value: T): Unit
}
trait Operations[T] {
def add(a: T, b: T): T
def multiply(a: T, b: T): T
}
// Implement the behaviors for each of the types you need
object IntStuff {
implicit object IntParser extends Parser[Int] {
override def parse(s: String): Int = Integer.valueOf(s)
}
implicit object IntWriter extends Writer[Int] {
override def write(value: Int): Unit = println(value)
}
implicit object IntOperations extends Operations[Int] {
override def add(a: Int, b: Int): Int = a + b
override def multiply(a: Int, b: Int): Int = a * b
}
}
// Define an algorithm on the type, put a context bound on it.
// This would make sure that the operations you need are supported for type `T`.
def writeSum[T: Parser : Writer : Operations](xs: String*): Unit = {
// Bring the implementation from implicit scope
val parser = implicitly[Parser[T]]
// Use the implementation
val values = xs.map(parser.parse)
if (values.nonEmpty) {
val writer = implicitly[Writer[T]]
val operations = implicitly[Operations[T]]
val sum = values.reduce(operations.add)
writer.write(sum)
}
}
// Bring the implementation to the implicit scope
import IntStuff._
// Enjoy :)
writeSum[Int]("1", "2", "3")
你能更具体地说明你遇到的麻烦吗?从你到目前为止所说的来看,并不明显你实际上走错了方向。这个例子被简化了,因为这种类型分布在所有系统中,有许多逻辑。无论如何,例如,我定义了一个UpdateAction[Int],它是来自(MyValueInt,MyValueInt)=>MyValueInt的函数,另一个UpdateAction[Double]对Double执行相同的操作。如果我把它们放在同一个列表中,并尝试映射和匹配不同的MyValue*案例,它就不会编译。如果我需要匹配(T,UpdateAction[T],MyValue[T]),那就更糟糕了。听起来很有趣。我建议将你的问题编辑成关于这一点的——用实际的代码和足够的细节,这样我们可以提供帮助。好的,我在过去一个小时里一直在尝试这条路。结果和你的有点不同,但这绝对是我需要的。我仍然有疑问,但在开始另一个问题之前,我会问你。在您的解决方案中,如何创建这些操作的列表?假设我读到一个表单输入(“10”、“0.001”、“香蕉”)。因此,我必须将第一个解析为Int,第二个解析为double,并将第三个解析为字符串。我从我已有的模式中知道这些类型,但是如何表达这个模式呢?编写或执行操作也是如此。一般情况下,会有一个高阶函数列表,每个函数都绑定到不同的类型,即IntStuff、DoubleStuff、StringStuff。例如,我可以将输入(字符串列表)压缩到解析器列表中,然后在需要时应用所有解析器(或操作或写入)。Hm。看起来类型类可能不是您想要的。当您想要在单个类型上泛化某些算法时,它们非常有用。请参阅,
writeSum
是对一些T
的概括,这些T具有一个解析器
、一个编写器
和一个为其实现的操作。但是T
在所有writeSum
方法中保持不变。据我所知,您希望在单一方法中使用不同的T
s。我说的对吗?是的。我的用例的另一个更有意义的部分是,我有一个形式为list[(T,T)=>T]的操作列表。这些可以成为部分应用的函数,但实际上不会改变任何东西。无论如何,这应该是一个单一的列表。现在我选择了列表的元组,类似于(List[UpdateAction[Int]],List[UpdateAction[Double]],List[UpdateAction[String]])。显然,这是一个痛苦的传递和操作,因为最终我只需要一个接一个地应用这些函数。如果你提供了一个你想解决的问题,这将有所帮助。用一些示例代码更新你的问题。此外,这可能是代码审查而不是stackoverflow的一个很好的候选者。