使用Monod或半群在日期列表中查找最小的日期



我试图构建一个函数,将日期数组折叠到最小的日期。我正在使用fp-ts,并且我想以一种功能的方式来完成它。

我第一次尝试使用Monoids来构建它,但是没有一个简单的方法来使用现有的原语来构建一个最小的monoid。然后我尝试使用半群,因为它们似乎有更好的构建块,我设法使它像这样工作:

const dates = [
new Date(2020, 1, 1, 1, 1, 1, 1),
new Date(2021, 1, 1, 1, 1, 1, 1),
new Date()
];
const minD = semigroup.concatAll(semigroup.min(date.Ord))(new Date())(dates);

然后我也设法使它使用Monoids工作,但我必须为Date类型构建一个有界实例,这需要一个顶部和一个底部值

const bdate: bounded.Bounded<Date> = {
top: new Date(),
bottom: new Date(0),
compare: date.Ord.compare,
equals: date.Ord.equals
};
const minDate = monoid.min(bdate);
const smallestDate = monoid.concatAll(minDate)(dates);

两种解决方案都在一定程度上起作用,但它们都有一个限制,那就是它们需要初始值来进行比较。在底部的情况下,这很容易,我可以只使用JS Date对象能够支持的第一个日期。但是,当您期望将来的日期位于要处理的日期数组中时,就不可能知道哪个值应该位于顶部。在这个例子中,我只提供了当前日期,但这是一个大胆的假设,可能发生的情况是日期列表中的最小日期是明天,而我将获得底部值。

是否有任何功能原语我错过了,能够积累比较下一个日期与前一个,并返回最小的一个?我想使用monoids和/或半群,因为fp-ts有很好的原语来围绕数据结构构建monoids,我希望创建一些数据管道处理器来计算统计数据,轻松地将数据结构与类似其形状的monoids折叠起来,但我被困在日期周围的第一个问题。

monoidsemigroup强迫您定义边界的原因是因为它们必须处理隐式的" empty ";的情况。如果你传入一个空的日期列表,concat函数应该返回什么值?

在我看来,你知道你有一个DateNonEmptyArray在这种情况下,问题变得非常容易解决使用该部分库的助手。例如:

import { pipe } from "fp-ts/lib/function";
import * as NEA from "fp-ts/lib/NonEmptyArray";
import { Ord as DateOrd } from "fp-ts/lib/Date";
const dates: NEA.NonEmptyArray<Date> = [
new Date(2020, 1, 1, 1, 1, 1, 1),
new Date(2021, 1, 1, 1, 1, 1, 1),
];
const minimum = pipe(
dates,
NEA.min(DateOrd),
);
console.log(minimum) // Logs the 2020 date

最新更新