Если вы действительно хотите, чтобы функция объединителя выполняла сопоставление, вы можете использовать fold
, но, как указал Крейг , вам нужно будет указать начальное значение:
def combine[A, B](f: B => A => B, zero: B)(xs: Iterable[Iterable[A]]) =
xs.foldLeft(Iterable(zero)) {
(x, y) => x.view flatMap { y map f(_) }
}
Тот факт, что вам нужно такое начальное значение, следует из типа функции объединителя / преобразователя (B, A) => B
(или, как функция карри, B => A => B
).Ясно, что для сопоставления первых A
, с которыми вы столкнетесь, вам потребуется указать B
.
. Вы можете сделать это несколько проще для вызывающих, используя класс типа Zero
:
trait Zero[T] {
def zero: T
}
object Zero {
implicit object IntHasZero extends Zero[Int] {
val zero = 0
}
// ... etc ...
}
Тогда метод combine
можно определить следующим образом:
def combine[A, B : Zero](f: B => A => B)(xs: Iterable[Iterable[A]]) =
xs.foldLeft(Iterable(implicitly[Zero[B]].zero)) {
(x, y) => x.view flatMap { y map f(_) }
}
Использование:
combine((b: Int) => (a: String) => b + a.length)(sets)
Scalaz обеспечивает Zero
класс type, а также множество других полезностей для функционального программирования.