我有interface
,如下所示:
interface FontRegionTransformer<R> {
fun transform(region: R, textCharacter: TextCharacter): R
}
我不是类别理论方面的专家,但是as I have learned previously这个结构是一个monoid (是吗?)我可以组合任意数量的函数{{1并且一起返回R
。
这就是我现在所拥有的:
R
这有效,但我有一个问题:如何将var image = source.getSubimage(meta.x * width, meta.y * height, width, height)
regionTransformers.forEach {
image = it.transform(image, textCharacter)
}
个List
组合成一个函数?我可以在不向界面添加FontRegionTransformer
功能的情况下执行此操作吗?我尝试使用compose
,但没有点击。
澄清:我想要实现的是将reduce
中存储的函数合并到一个函数中,而不是在这里循环:
regionTransformers
我想要这样的事情:
var image = source.getSubimage(meta.x * width, meta.y * height, width, height)
regionTransformers.forEach {
image = it.transform(image, textCharacter)
}
答案 0 :(得分:3)
对于构图定义,不太清楚,当调用组合变换器时,第二个textCharacter
应该得到FontRegionTransformer<R>
。在这里,我假设它与传递给调用的textCharacter
相同,并且自然地传递给第一个变换器。
您可以将自定义合成操作实现为FontRegionTransformer<R>
的扩展名:
fun <R> FontRegionTransformer<R>.compose(other: FontRegionTransformer<R>) =
object : FontRegionTransformer<R> {
override fun transform(region: R, textCharacter: TextCharacter): R {
val firstResult = this@compose.transform(region, textCharacter)
return other.transform(firstResult, textCharacter)
}
}
您可以将infix
modifier添加到compose
以使用中缀符号a compose b
,或者将其设为overload an operator +
or *
,如果您想将其称为a * b
1}}。或者使用非扩展程序顶级函数进行compose(a, b)
调用。
然后你可以撰写两个FontRegionTransformer
s:
val composed = first.compose(second)
要将变换器列表合并为一个,请使用reduce
:
val transformers: List<FontRegionTransformer<SomeType>> = TODO()
val composition = transformers.reduce { a, b -> a.compose(b) }
要使FontRegionTransformer<R>
成为幺半群,合成操作应该是关联的(a ∘ (b ∘ c)
应该等同于(a ∘ b) ∘ c
所有a
,b
和{{ 1}})以上的实现似乎满足了这个要求。但是,严格地说,它也应该有一个中性元素,例如c
,n
代表任何a ∘ n = n ∘ a = a
。这两个要求不能用Kotlin类型系统来表达,而应该是合同的一部分。
一种语句解决方案是将a
内嵌到compose
来电:
reduce