簡體   English   中英

在scala中組成一系列可變類型的功能

[英]Composing a sequence of functions of variable types in scala

我想做的是對數據集應用一系列轉換,其中每個函數獲取上一步的輸出並將其轉換為下一步。 例如

val f1: Function1[Int, Double] = _ / 2d
val f2: Function1[Double, BigDecimal] = x=>BigDecimal(x - 2.1)
val f3: Function1[BigDecimal, String] = _.toString

val chained = (f1 andThen f2 andThen f3)(_)

println(chained(10))

我想要的是一個函數f,它接受一個輸入Seq(f1,f2,...)並返回它們的鏈接,其中f1,f2,... fn並非都具有相同的輸入和相同的輸出類型T。但是它們是可組合的,因此例如:

f1: Function1[A,B]
f2: Function1[B,C]
f3: Function1[C,D]

然后鏈接函數將返回函數f:[A,D]。

謝謝Z

這里有兩個解決方案建議:

  1. 一個需要特殊種類列表的解決方案,可以跟蹤功能鏈中的所有類型。
  2. 適用於普通列表的asInstanceOf解決方案。

跟蹤所有類型的中間結果

普通列表將無法跟蹤所有中間結果的類型。 這是跟蹤所有這些類型的函數的列表:

sealed trait Func1List[-In, +Res] {
  def ::[I, O <: In](h: I => O): Func1List[I, Res] = ConsFunc1(h, this)
}
object Func1List {
  def last[In, Res](f: In => Res): Func1List[In, Res] = LastFunc1(f)
  def nil[A]: Func1List[A, A] = LastFunc1(identity)
}

case class LastFunc1[-In, +Res](f: In => Res) 
  extends Func1List[In, Res]
case class ConsFunc1[-In, Out, +Res](head: In => Out, tail: Func1List[Out, Res]) 
  extends Func1List[In, Res]

現在,對於Func1List ,我們可以定義一個連接所有元素的函數:

def andThenAll[A, Z](fs: Func1List[A, Z]): A => Z = fs match {
  case LastFunc1(f) => f
  case c: ConsFunc1[A, t, Z] => c.head andThen andThenAll[t, Z](c.tail)
}

一點測試:

val f1: Function1[Int, Double] = _ / 2d
val f2: Function1[Double, BigDecimal] = x => BigDecimal(x - 2.1)
val f3: Function1[BigDecimal, String] = _.toString

val fs = f1 :: f2 :: Func1List.last(f3)
val f = andThenAll(fs)

println(f(42)) // prints 18.9

只是asInstanceOf所有的事情

稍微不完善但更短的解決方案:

def andThenAll[X, Y](fs: List[_ => _]): X => Y = fs match {
  case Nil => (identity[X] _).asInstanceOf[X => Y]
  case List(f) => f.asInstanceOf[X => Y]
  case hd :: tl => hd match {
    case f: Function1[X @unchecked, o] => f andThen andThenAll[o, Y](tl)
  }
}

這也導致18.9

println(andThenAll[Int, String](List(f1, f2, f3))(42))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM