是否可以实施"很好地"在kotlin?

时间:2017-04-23 12:01:13

标签: functional-programming kotlin applicative

我已经定义了Result这样的类型:

sealed class BadResult {
    data class Description(val description: String): BadResult()
    data class Exception  (val exception  : Throwable): BadResult()
}

sealed class BadTree {
    data class Leaf(val v: BadResult)                : BadTree()
    data class Fork(val l: BadTree, val r: BadTree)  : BadTree()
}

sealed class Result<T> {
    data class Good<T>     (val good     : T     )      : Result<T>()
    class Empty<T>                                      : Result<T>()
    data class Bad <T>     (val badTree  : BadTree   )  : Result<T>()
}

fun <T> T.good()        : Result<T> = Result.Good(this)
fun <T> empty()         : Result<T> = Result.Empty()
fun <T> BadTree.bad()   : Result<T> = Result.Bad<T>(this)
fun <T> String.bad()    : Result<T> = BadTree.Leaf(BadResult.Description(this)).bad()
fun <T> Throwable.bad() : Result<T> = BadTree.Leaf(BadResult.Exception(this)).bad()

对于这个Result课程,我定义了monadic bind

infix fun <T, U> Result<T>.bind(uf: (T) -> Result<U>) : Result<U> {
    return when(this) {
        is Result.Good  -> uf(this.good)
        is Result.Empty -> empty()
        is Result.Bad   -> this.badTree.bad()
    }
}

一个非常有用的函数模式是Applicative,如果应用于Result,这将允许我调用带有arbritrary参数列表的函数,当且仅当所有参数都是Good时。

这是一种通常依赖于部分应用(又称currying)的技术,其中AFAIK在kotlin中不支持开箱即用。我已经看到一些图书馆尝试做曲,但在我看来,curry并不是kotlin中普遍认可的习语。

我理想的写作是这样的:

pure(::aFunctionThatTakes3Args) apply arg1 apply arg2 apply arg3

但我无法想出签名的样子。

我可以为函数的每个arity创建一个lift函数,但很快就会变得很麻烦。

lift(::aFunctionThatTakes3Args, arg1, arg2, arg3) // lift is overloaded for each arity

(这似乎是funKTionale实现currying的方式)

欢迎任何想法。

0 个答案:

没有答案