Scala:折叠一系列具有不同签名的操作?

时间:2016-10-07 22:14:53

标签: scala types

我想编写一组每个实现特定操作的类,因此它们接受某种类型的参数并返回相同类型或不同类型的参数。然后,给出这些操作的列表,折叠初始值,依次应用每个操作,并将结果提供给列表中的下一个操作。

例如,像这样:

val program = List[Operation](Add3, ToString, Repeat5)
program.foldLeft(5) ((progress, operation) => operation.apply(progress))

所以第一个操作加3,第二个把它变成一个字符串,最后一个重复5次。这将导致:

"88888"

如何在Scala中实现这类功能?

谢谢!

2 个答案:

答案 0 :(得分:1)

List中使用不同签名的方法很难以类型安全的方式进行,但您可以采用不同的方式对其进行排列。

def add3(i: Int): Float = i + 3.1f
def num2string(f: Float): String = f"$f%.1f"
def repeat5(s: String): String = s * 5

val all = add3 _ andThen num2string andThen repeat5

all(6)  // res0: String = 9.19.19.19.19.1

请注意,编译器不允许您以错误的顺序放置这些方法。这是一个很好的功能,你不会使用List操作。

andThen操作链可以在运行时动态构建,或多或少与构建List相同。

从参数类型开始。 (在您的示例中,Int。)

val ops0: Int => Int = identity _

现在您有一个Int => Int功能,您可以根据当前条件添加或不添加操作。类型总是Int => ??在哪里?是添加到链中的最后一个操作的返回类型。

答案 1 :(得分:1)

你可以做这样的事情。不鼓励瓦尔,但此时这是我提出的最好的

abstract class Operation
  case class Add3() extends Operation with Function[Int, Int] {
    def apply(x: Int) = x + 3
  }

  case class ToString() extends Operation with Function[Int, String] {
    def apply(x: Int) = x.toString
  }

  case class Repeat5() extends Operation with Function[String, String] {
    def apply(s: String) = s * 5
  }

  val lst = List[Operation](Add3(), ToString(), Repeat5())
  var v = "5"
  lst.foreach { op =>
    {
      v = op match {
        case op: Add3     => op.apply(v.toInt).toString
        case op: ToString => op.apply(v.toInt)
        case op: Repeat5  => op.apply(v)
      }
    }
  }

  println(v)