【发布时间】:2018-05-08 22:30:20
【问题描述】:
我是函数式编程和 Kotlin 的绝对初学者,试图解决我根据自己提出的问题创建的练习;我目前的问题是“如何使用端口和适配器架构将函数式编程应用到现实世界的应用程序中?”
目前正在学习Either monad,我有以下函数,其中Perhaps<T> 只是一个重命名的Either<Err, T>,用于exception handling。
这个函数接受一个包含任意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) }
}
一开始我希望使用return 和apply 因为这两个方法调用perhapsExtractLocalDate 是独立的,所以我会使用applicative 样式。相反,我无法弄清楚如何避免使用bind,据我了解,这意味着一种单子风格。
我的问题是:
如果我的理解是正确的,我怎么能把它变成applicative style?
在上述实现中是否存在严重错误? (即成语、柯里化的误用)
【问题讨论】:
标签: functional-programming kotlin continuation-passing