【发布时间】:2013-02-11 03:51:51
【问题描述】:
我想实现以下目标:
- 有一个我需要处理的字符串列表。
- 这些处理器有几种不同的种类,每一种都知道要读取字符串的哪一部分。
- 我需要分两个阶段工作:首先,处理器需要查看每个输入字符串以构建特定于处理器的数据;其次,每个输入字符串由每个处理器处理,并将生成的字符串合并为一个。
以可变的方式很容易做到这一点:所有处理器都有一个通用的基类,它们聚合的不同类型的数据被封装在具体的实现中;该界面仅包含 2 个功能——“查看输入字符串并构建内部数据”和“使用您的内部数据处理输入字符串”。
当我在 Scala 中编写它时,我想知道是否存在纯函数式方法。问题是现在这些处理器的基本特征是由它们的内部数据类型参数化的,而且似乎没有办法列出不同类型的处理器。
这个问题可以用一个更简单的例子来证明:假设我会坚持使用可变方法,但由于某种原因已经参数化了处理器从字符串中获取的类型:
trait F[V] {
def get(line: String) : V
def aggregate(value: V)
def process(value: V) : String
}
class F1 extends F[Int] // ...
class F2 extends F[HashMap[Int, Int]] // ...
for (s <- List("string1", "string2");
f <- List(new F1(), new F2())
{
f.aggregate(f.get(s)); // Whoops --- doesn't work
}
它不起作用,因为f.get(s) 返回Any。看起来我需要在 Scala 的类型系统中表达 List(new F1(), new F2()) 包含 F[?] 是不同但一致的,如果我采用该列表的一个元素,它的类型参数有一些具体值,而 f.get(s) 是那种类型,应该被f.aggregate()接受。
最后,我想要这样的东西(因为我不知道怎么做所以有遗漏):
trait F[D] {
def initData : D
def aggregate(line: String, data: D) : D
def process(line: String, data: D) : String
}
class F1 extends F[Int] // ...
class F2 extends F[HashMap[Int, Int]] // ...
// Phase 1
// datas --- List of f.initData, how to?
for (s <- List("string1", "string2")) {
for (f <- List(new F1(), new F2()) {
// let fdata be f's data
// update fdata with f.aggregate(s, fdata)
}
}
// Phase 2
for (s <- List("string1", "string2")) {
for (f <- List(new F1(), new F2()) {
// let fdata be f's data
// for all fs, concatenate f.process(s, fdata) into an output string
}
}
问题:
- 这个任务是否可以在 Scala 中以纯函数方式解决?
- 这个任务可以用其他函数式语言解决吗?
- 这种情况看起来很一般。有它的名字我可以搜索吗?
- 如果几乎没有类型理论和函数式编程语言的背景,哪里是阅读它的最佳地点?
【问题讨论】:
-
你能扩展你的第二个例子吗?您希望以何种顺序应用您的功能尚不清楚。据我了解,您希望您的项目特定数据计算如下: d1 = process(aggregate("s2", aggregate("s1", f1.initData)) ?但是如何使用此数据处理字符串? process(" s1", d1), process("s2", d2) ?还是别的什么?
-
这听起来像是一个非常简单的两阶段
mapping 管道。或者map后跟reduce...我认为有一个名字... -
@alno:抱歉,问题中的代码很不清楚。我澄清了一点。
标签: scala generics types functional-programming