在 fp-ts 中,如何组合 2 个(或更多)Ord 实例

In fp-ts, how to compose 2 (or more) Ord instances

假设我有一个字符串列表,我想先按字符串长度对它们进行排序,然后再按字母顺序排序(因此列表中具有相同长度的字符串按字母顺序排序)。

我已经有 ordString 可用于按字母顺序排序。我可以为字符串长度创建自己的 Ord 实例:

import * as S from 'fp-ts/string'
import * as N from 'fp-ts/number'
import * as Ord from 'fp-ts/Ord'

const ordString = S.Ord

const ordStringLength = pipe(N.Ord, Ord.contramap((s: string) => s.length))

如果我想使用这些 Ord 对我的列表进行排序,我可以调用 A.sort 两次,但这似乎很浪费:

import * as A from 'fp-ts/Array'

const sorted = pipe(listOfStrings, A.sort(ordString), A.sort(ordStringLength))

有什么方法可以将 ordStringordStringLength 实例组合成一个实例,可以在对 A.sort 的单次调用中使用?

(这是一个人为的例子来证明我的问题;实际上排序更复杂,可能涉及组合多个 Ords)

Ord有一个Monoid实例,可以用来做你想做的事;也就是说,先用一个 Ord 下单,然后再用另一个

fp-tsdocs

中有一个很好的例子

简而言之,你应该可以做到

import { sort } from 'fp-ts/Array'
import { getMonoid } from 'fp-ts/Ord'
import { concatAll } from 'fp-ts/Monoid'

const M = getMonoid<string>
const byBothOrds = concatAll(M)([ordString, ordStringLength])
const sorted = sort(byBothOrds)(listOfStrings)

如您所问,如何向其中添加额外的 Ord 应该是相当明显的。