我是函数编程和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) }
}
起初,我曾期望使用
return
和apply
,因为这两个方法调用perhapsExtractLocalDate
是独立的,因此我将使用一种应用样式。取而代之的是,我无法弄清楚如何避免使用bind
,据我所知,这意味着单调风格。我的问题是:
最佳答案
我相信我理解出了什么问题。
在用适当的函数式编程语言编写的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/