函数式编程依赖:如何在没有直接连接在一起的函数之间共享依赖
Functional Programming Dependencies: How to share dependencies between functions that aren't connected together direct
这些不同的函数像这样组合在一起[=13=]
f1 -> f2 -> f3 -> f4 -> f5
我需要在 f3 周围添加两个新函数 fx 和 fy,如下所示:
f1 -> f2 -> fx -> f3 -> fy -> f4 -> f5
所以我需要预处理 f3 的参数,然后 post 处理 f3
的输出
此处函数 fx 进行了更改,fy 将更改还原,但 fy 需要 fx 的其他详细信息才能还原,例如要知道要还原到哪些值
问题是函数 fx 需要产生两个输出
first: output that is needed by f3
second: output that is needed by fy
问题:
如何在没有直接连接在一起的函数之间共享依赖关系,
有空间 way/technique 来解决这个问题吗?
仅供参考,我正在使用 Java8
我通过创建 fk 函数来解决这个问题,该函数通过在它之前调用 fx 并在它之后调用 fy 来包装 f3,这样我就能够共享所需的状态位,这类似于 Aadit 建议的箭头。
我将对所有函数 return 值使用某种类型 A
;您将需要自己整理出真实的类型。
这是您描述的意图:
- 函数
fx
将产生两个参数,我们称它们为a
和b
。
- 函数
f3
将处理值 a
并产生 a'
.
- 最后,
fy
将消耗 a'
和 b
并产生 c
。
让我们看看如何实现(我将为类型签名编写伪代码):
将 fy
定义为接受两个参数和 return 一个参数的函数:
(A, A) => A
定义 fyp
("fy preprocessed" 的缩写)作为一个函数,它采用一些预处理函数 p
并执行您的 fy
的逻辑,但第一个参数使用 p
进行了预处理。我们将把它写成 P => FY
的形式,其中 P
是预处理函数的类型签名, FY
是 fy
的类型签名:
P => FY, which expands to
(A => A) => (A, A) => A
所以这个函数的实现应该以A => A
类型的预处理函数p
作为输入,执行fy
的逻辑(这是右边,(A, A) => A
...注意它是如何对应fy
)的签名的,但是在执行逻辑之前,它会将fy
的第一个参数映射到p
。这里有一些 Scala 实现供参考(我不太擅长 Java):
val fyp: (A => A) => ((A, A)) => A =
f => fyuParams => performFyLogic((f(fyuParams._1), fyuParams._2))
其中 performFyLogic
是您的 fy
函数的实际处理逻辑。
定义最终构图为:
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
这些不同的函数像这样组合在一起[=13=]
f1 -> f2 -> f3 -> f4 -> f5
我需要在 f3 周围添加两个新函数 fx 和 fy,如下所示:
f1 -> f2 -> fx -> f3 -> fy -> f4 -> f5
所以我需要预处理 f3 的参数,然后 post 处理 f3
的输出此处函数 fx 进行了更改,fy 将更改还原,但 fy 需要 fx 的其他详细信息才能还原,例如要知道要还原到哪些值
问题是函数 fx 需要产生两个输出
first: output that is needed by f3
second: output that is needed by fy
问题: 如何在没有直接连接在一起的函数之间共享依赖关系, 有空间 way/technique 来解决这个问题吗?
仅供参考,我正在使用 Java8
我通过创建 fk 函数来解决这个问题,该函数通过在它之前调用 fx 并在它之后调用 fy 来包装 f3,这样我就能够共享所需的状态位,这类似于 Aadit 建议的箭头。
我将对所有函数 return 值使用某种类型 A
;您将需要自己整理出真实的类型。
这是您描述的意图:
- 函数
fx
将产生两个参数,我们称它们为a
和b
。 - 函数
f3
将处理值a
并产生a'
. - 最后,
fy
将消耗a'
和b
并产生c
。
让我们看看如何实现(我将为类型签名编写伪代码):
将
fy
定义为接受两个参数和 return 一个参数的函数:(A, A) => A
定义
fyp
("fy preprocessed" 的缩写)作为一个函数,它采用一些预处理函数p
并执行您的fy
的逻辑,但第一个参数使用p
进行了预处理。我们将把它写成P => FY
的形式,其中P
是预处理函数的类型签名,FY
是fy
的类型签名:P => FY, which expands to (A => A) => (A, A) => A
所以这个函数的实现应该以
A => A
类型的预处理函数p
作为输入,执行fy
的逻辑(这是右边,(A, A) => A
...注意它是如何对应fy
)的签名的,但是在执行逻辑之前,它会将fy
的第一个参数映射到p
。这里有一些 Scala 实现供参考(我不太擅长 Java):val fyp: (A => A) => ((A, A)) => A = f => fyuParams => performFyLogic((f(fyuParams._1), fyuParams._2))
其中
performFyLogic
是您的fy
函数的实际处理逻辑。定义最终构图为:
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