2

这些不同的功能像这样组合在一起

f1 -> f2 -> f3 -> f4 -> f5

我需要在 f3 周围添加两个新函数 fx 和 fy,如下所示:

f1 -> f2 -> fx -> f3 -> fy -> f4 -> f5

所以我需要预处理 f3 的参数,然后对 f3 的输出进行后处理

这里函数 fx 进行更改, fy 将更改恢复,但 fy 需要 fx 的其他详细信息才能恢复,例如要知道要恢复到哪些值

问题是函数 fx 需要产生两个输出

first: output that is needed by f3
second: output that is needed by fy

问题:如何在未直接连接在一起的函数之间共享依赖关系,是否有解决此问题的空间方式/技术?

仅供参考,我正在使用 Java8

4

2 回答 2

1

我通过创建 fk 函数来解决这个问题,该函数通过调用 fx 之前和之后调用 fy 来包装 f3,这样我就能够共享所需的状态位,这类似于 Aadit 建议的箭头。

于 2019-05-22T09:34:16.073 回答
1

我将对所有函数返回值使用某种类型A;你需要自己整理出真正的类型。

这是您描述的意图:

  • 函数fx将产生两个参数,我们称它们为ab
  • 函数f3将处理 valuea和 yield a'
  • 最后,fy将消费a'b生产c

让我们看看我们如何实现这一点(我将为类型签名编写伪代码):

  1. 定义fy为一个接受两个参数并返回一个参数的函数:

    (A, A) => A
    
  2. 定义fyp(“fy preprocessed”的缩写)作为一个函数,它接受一些预处理函数p并执行你的逻辑fy,但第一个参数用p. 我们将把它写成P => FY,其中P是预处理函数FY的类型签名, 是 的类型签名fy

    P => FY, which expands to  
    (A => A) => (A, A) => A
    

    所以这个函数的实现应该以ptype的预处理函数A => A作为输入,执行fy(这是右手边,(A, A) => A...注意它是如何对应的签名的fy)的逻辑,但是在执行逻辑之前,它会映射fywith的第一个参数p。这是一些 Scala 实现供参考(我对 Java 不太擅长):

    val fyp: (A => A) => ((A, A)) => A =              
      f => fyuParams => performFyLogic((f(fyuParams._1), fyuParams._2))  
    

    你的函数performFyLogic的实际处理逻辑在哪里。fy

  3. 将最终组合定义为:

    f1 -> f2 -> fx -> fyp(f3)
    

这是完整的 Scala 实现供参考(同样,不太了解 Java 8):

val f1: Int => Int = _ + 1
val f2: Int => Int = _ + 2
val f3: Int => Int = _ + 3

val fx: Int => (Int, Int) = i => (i + 4, i + 5)

// let's assume that the original fy simply sums up its two parameters
val fyp: (Int => Int) => ((Int, Int)) => Int =
  f => fyArgs => f(fyArgs._1) + fyArgs._2

val composed1 = f1 andThen f2 andThen f3
println(composed1(42)) // 48

val composed2 = f1 andThen f2 andThen fx andThen fyp(f3)
println(composed2(42)) // 102

// because:
// f1 -> f2 -> fx = (42 + 1 + 2 + 4, 41 + 1 + 2 + 5) = (49, 50)
// fyp(f3)((49, 50)) = (49 + 3) + 50 = 102    
于 2019-05-22T09:34:43.973 回答