#typescript #functional-programming #fp-ts
Вопрос:
Допустим, у меня есть список строк, и я хочу отсортировать их сначала по длине строки, а затем по алфавиту (поэтому строки в списке с одинаковой длиной сортируются в алфавитном порядке).
У меня уже есть 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
s для сортировки моего списка, я могу вызвать A.sort
дважды, но это кажется расточительным:
import * as A from 'fp-ts/Array'
const sorted = pipe(listOfStrings, A.sort(ordString), A.sort(ordStringLength))
Есть ли способ, которым я могу объединить ordString
ordStringLength
экземпляры and в один экземпляр, который можно использовать в одном вызове to A.sort
?
(это надуманный пример, демонстрирующий мой вопрос; на самом деле порядок более сложный и может включать объединение нескольких Ord
экземпляров)
Комментарии:
1. Я не уверен, потому что я не
fp-ts
пользователь, но я вижу, чтоOrd
у него есть экземпляр полугруппы, который, вероятно, вам нужен2. Я думаю, что это ответ. Теперь просто нужно выяснить, как построить соответствующую полугруппу
Ответ №1:
Ord
имеет Monoid
экземпляр, который можно использовать для выполнения того, что вы хотите; то есть сначала упорядочить с одним Ord
, затем с другим.
В fp-ts
документах есть довольно хороший пример
короче говоря, вы должны быть в состоянии сделать
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
s к этому, как вы просили.
Комментарии:
1. есть ли хорошее руководство для fp-ts? Насколько я понял, чтобы изучить fp-ts, вам нужно прочитать исходный код: (
2. Честно говоря, я мог и должен был ссылаться на документы, а не на исходный код
3. Спасибо. Я пытаюсь изучить fp-ts, иногда он выглядит совершенно нечитаемым, по крайней мере, для меня
4. Неплохо. Я действительно пошел с
Ord.getSemigroup<string>().concat(ordStringLength, ordString)
тем, что, кажется, делает свое дело.5. Для пояснения:
Ord
является классом типа и, следовательно, не может быть экземпляром другого. Единственное отношение между классами типов — это подкласс / суперкласс. НоOrdering
у типа данных естьMonoid
экземпляр.Ordering
это просто оболочка типа вокруг-1/0/1
компаратора.