如何在Kotlin中使用兼容的参数/结果类型编写函数?

时间:2017-08-15 20:38:58

标签: functional-programming kotlin

我有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)
}

1 个答案:

答案 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所有ab和{{ 1}})以上的实现似乎满足了这个要求。但是,严格地说,它也应该有一个中性元素,例如cn代表任何a ∘ n = n ∘ a = a。这两个要求不能用Kotlin类型系统来表达,而应该是合同的一部分。

一种语句解决方案是将a内嵌到compose来电:

reduce