functional-programming - Kotlin Either monad:重构构造函数调用以处理CPS

标签 functional-programming kotlin continuation-passing

我是函数编程和Kotlin的绝对初学者,试图解决我根据自己提出的问题创建的练习;我当前的问题是“如何使用端口和适配器体系结构将函数式编程实践应用到现实世界中的应用程序?”

当前正在学习Either monad,我具有以下功能,其中Perhaps<T>只是与exception handling一起使用的重命名的Either<Err, T>

此函数采用包含任意HTTP参数的RequestModel,并且Perhaps可以返回CountBetweenQuery,它只是一个包含两个LocalDate的数据类。

private fun requestCountBetweenQueryA(model: RequestModel): Perhaps<CountBetweenQuery> {
    return try {
        Perhaps.ret(CountBetweenQuery(extractLocalDateOrThrow(model, "begin"), extractLocalDateOrThrow(model, "end")))

    } catch (e: UnsupportedTemporalTypeException) {
        Perhaps.Fail(Err.DATE_FORMAT_IS_INVALID)

    } catch (e: DateTimeException) {
        Perhaps.Fail(Err.DATE_FORMAT_IS_INVALID)
    }
}

private fun extractLocalDateOrThrow(it: RequestModel, param: String): LocalDate =
        LocalDate.from(DateTimeFormatter.ISO_DATE.parse(it.parameters.first { it.key == param }.value))

在OO语言中,我将对其进行重构,以使异常处理可以在通用异常处理程序中以下面的方式进行,或者以更高的方式(将重复的代码提取到单个方法中)进行处理。自然,我想将extractLocalDateOrThrow转换为perhapsExtractLocalDate作为练习的一部分:
private fun perhapsExtractLocalDate(it: RequestModel, param: String): Perhaps<LocalDate> = try {
    Perhaps.ret(LocalDate.from(DateTimeFormatter.ISO_DATE.parse(it.parameters.first { it.key == param }.value)))

} catch (e: UnsupportedTemporalTypeException) {
    Perhaps.Fail(Err.DATE_FORMAT_IS_INVALID)

} catch (e: DateTimeException) {
    Perhaps.Fail(Err.DATE_FORMAT_IS_INVALID)
}

我努力了一个小时,试图弄清楚如何在保留延续传递样式的同时调用CountBetweenQuery的构造函数。

这是我想出的:
private fun requestCountBetweenQueryB(me: RequestModel): Perhaps<CountBetweenQuery> {
    val newCountBetweenQueryCurried: (begin: LocalDate) -> (end: LocalDate) -> CountBetweenQuery =
            ::CountBetweenQuery.curried()

    return Perhaps.ret(newCountBetweenQueryCurried)
            .bind { function -> perhapsExtractLocalDate(me, "begin").map(function) }
            .bind { function -> perhapsExtractLocalDate(me, "end").map(function) }
}

起初,我曾期望使用returnapply,因为这两个方法调用perhapsExtractLocalDate是独立的,因此我将使用一种应用样式。取而代之的是,我无法弄清楚如何避免使用bind,据我所知,这意味着单调风格。

我的问题是:
  • 如果我的理解是正确的,该如何将其转变为应用风格?
  • 在上述实现中是否犯了重大错误? (即成语,滥用 curry )
  • 最佳答案

    我相信我理解出了什么问题。

    在用适当的函数式编程语言编写的FP示例中,应用风格的书写方式类似于someFunction map a apply b,但在Kotlin中,由于我们处理的是对象方法,因此从左向右读取时按保留顺序编写,但按正确的顺序编写。论证评估条款。这让我非常困惑。

    private fun requestCountBetweenQueryC(me: RequestModel): Perhaps<CountBetweenQuery> {
        val newCountBetweenQueryCurried: (begin: LocalDate) -> (end: LocalDate) -> CountBetweenQuery =
                ::CountBetweenQuery.curried()
    
        val a = perhapsExtractLocalDate(me, "begin")
        val b = perhapsExtractLocalDate(me, "end")
    
        return b.apply(a.map(newCountBetweenQueryCurried))
    }
    

    如果我的理解是正确的,则也称为lift2函数。

    关于functional-programming - Kotlin Either monad:重构构造函数调用以处理CPS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47481218/

    相关文章:

    java - 在高阶函数中调用带有参数的 lambda

    intellij-idea - Kotlin 多平台 : sharing actual class implementation for multiple targets (iOS, macOS)

    java - 在 Kotlin 中扩展泛型类

    java - 我的 OnNavigationItemSelectedListener kotlin android 有什么问题吗?

    f# - 为什么延续要避免stackoverflow?

    list - 最大算法haskell

    python - 添加到多索引 DataFrame 时如何维护 lexsort 状态?

    python - python 闭包什么时候进行捕获?

    c# - 连续传递风格的中间值和返回值