用andThen减少不同类型的函数 [英] Reduce with andThen across functions of different types

查看:35
本文介绍了用andThen减少不同类型的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想以编程方式组合多个函数.如果这些函数都是相同类型的,我可以执行以下操作:

I want to programmatically compose several functions. If these functions are all of the same type, I can do the following:

def a(x: Int): Int = x+1
def b(y: Int): Int = y/2
def c(z: Int): Int = z*4
val f1 = (a _) andThen (b _) andThen (c _)
val f2 = List((a _), (b _), (c _)).reduce(_ andThen _)

此时 f1f2 是同一个东西,这编译是因为定义了 f2List> 是一个 List[Function1[Int,Int]]

At which point f1 and f2 are the same thing, and this compiles because the List that defines f2 is a List[Function1[Int,Int]]

但是,如果我想使用相同的基本 reduce 技术将具有不同类型的多个兼容函数链接在一起,则会出现错误.

However, if I want to chain together multiple compatible functions with different types using the same basic reduce technique, I get an error.

def d(x: Double): Int = x.toInt
def e(y: Int): String = y.toString
def f(z: String): Double = z.toDouble*4

//Works fine
val f3 = (d _) andThen (e _) andThen (f _)

//Doesn't compile
val f4 = List((d _), (e _), (f _)).reduce(_ andThen _)

第二个选项无法编译,因为定义 f4 的列表被推断为 List[Function1[Any,Any]],但我想不通如果有一种干净的类型安全的方法来获取形式为 Function1[A,B],Function1[B,C],Function1[C,D],...,Function1[X] 的有序函数集合,Y] 并将它们粘合在一起作为 Function1[A,Y] 像这样.

The second option doesn't compile because the list that defines f4 is inferred as a List[Function1[Any,Any]], but I can't figure out if theres a clean type-safe way to take an ordered collection of functions of the form Function1[A,B],Function1[B,C],Function1[C,D],...,Function1[X,Y] and glue them together as a Function1[A,Y] like this.

有什么想法吗?

推荐答案

这里有两个问题.第一个(正如您所指出的)是列表具有单个元素类型,它将被推断为它包含的元素类型的最小上限,在这种情况下是极其无聊和无用的 带双精度的字符串 =>任何.异构列表提供了解决这部分问题的一种方法,我将在稍后展示.

There are two problems here. The first (as you've noted) is that the list has a single element type, which will be inferred to be the least upper bound of the types of the elements it contains, which in this case is the extremely boring and useless String with Int with Double => Any. Heterogeneous lists provide one way of addressing this part of the problem, as I'll show in a second.

第二个问题是 _ andThen _ 不够多态(正如 Bob Dalgleish 在上面的评论中指出的那样).reduce 的参数将是一个具有具体输入类型和具体输出类型的函数,所以即使我们有一个异构列表,我们也无法用 Function 来自 Scala 标准库——我们需要一个 多态函数值代替.

The second problem is that the _ andThen _ is insufficiently polymorphic (as Bob Dalgleish points out in a comment above). The argument to reduce will be a function with a concrete input type and a concrete output type, so even if we had a heterogeneous list, there's no way we could reduce it with a Function from the Scala standard library—we'd need a polymorphic function value instead.

幸运的是(如果你真的想在 Scala 中做这种事情),有一个很棒的库,叫做 Shapeless 提供了异构列表和多态函数的良好实现.例如,您可以编写以下内容:

Fortunately (if you really want to do this kind of thing in Scala), there's a great library called Shapeless that provides nice implementations of both heterogeneous lists and polymorphic functions. For example, you could write the following:

def d(x: Double): Int = x.toInt
def e(y: Int): String = y.toString
def f(z: String): Double = z.toDouble * 4

import shapeless._

object andThen extends Poly2 {
  implicit def functions[A, B, C] = at[A => B, B => C](_ andThen _)
}

然后:

scala> val andThenned = HList((d _), (e _), (f _)).reduceLeft(andThen)
andThenned: Double => Double = <function1>

scala> andThenned(13.0)
res0: Double = 52.0

我觉得这很整洁.

这篇关于用andThen减少不同类型的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆